~netlandish/django-wiki

e617e018d614f4ccbc5a75ee7415773efb715b5c — Mads Jensen 6 years ago 27ab0a2
Switched to Python 3's super() syntax.
M src/wiki/admin.py => src/wiki/admin.py +2 -2
@@ 21,7 21,7 @@ class ArticleRevisionForm(forms.ModelForm):
        exclude = ()

    def __init__(self, *args, **kwargs):
        super(ArticleRevisionForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        # TODO: This pattern is too weird
        editor = editors.getEditor()
        self.fields['content'].widget = editor.get_admin_widget()


@@ 55,7 55,7 @@ class ArticleForm(forms.ModelForm):
        exclude = ()

    def __init__(self, *args, **kwargs):
        super(ArticleForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        if self.instance.pk:
            revisions = models.ArticleRevision.objects.filter(
                article=self.instance)

M src/wiki/core/markdown/__init__.py => src/wiki/core/markdown/__init__.py +1 -1
@@ 33,7 33,7 @@ class ArticleMarkdown(markdown.Markdown):
        return extensions

    def convert(self, text, *args, **kwargs):
        html = super(ArticleMarkdown, self).convert(text, *args, **kwargs)
        html = super().convert(text, *args, **kwargs)
        if settings.MARKDOWN_SANITIZE_HTML:
            tags = settings.MARKDOWN_HTML_WHITELIST + plugin_registry.get_html_whitelist()


M src/wiki/core/markdown/mdx/codehilite.py => src/wiki/core/markdown/mdx/codehilite.py +1 -1
@@ 42,7 42,7 @@ class WikiFencedBlockPreprocessor(Preprocessor):
    CODE_WRAP = '<pre>%s</pre>'

    def __init__(self, md):
        super(WikiFencedBlockPreprocessor, self).__init__(md)
        super().__init__(md)

        self.checked_for_codehilite = False
        self.codehilite_conf = {}

M src/wiki/core/paginator.py => src/wiki/core/paginator.py +2 -2
@@ 8,12 8,12 @@ class WikiPaginator(Paginator):
        :param side_pages: How many pages should be shown before and after the current page
        """
        self.side_pages = kwargs.pop('side_pages', 4)
        super(WikiPaginator, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)

    def page(self, number):
        # Save last accessed page number for context-based lookup in page_range
        self.last_accessed_page_number = number
        return super(WikiPaginator, self).page(number)
        return super().page(number)

    @property
    def page_range(self):

M src/wiki/editors/markitup.py => src/wiki/editors/markitup.py +2 -2
@@ 19,7 19,7 @@ class MarkItUpAdminWidget(BuildAttrsCompat, forms.Widget):
                         'rows': '10', 'cols': '40', }
        if attrs:
            default_attrs.update(attrs)
        super(MarkItUpAdminWidget, self).__init__(default_attrs)
        super().__init__(default_attrs)

    def render(self, name, value, attrs=None, renderer=None):
        if value is None:


@@ 40,7 40,7 @@ class MarkItUpWidget(BuildAttrsCompat, forms.Widget):
                         'rows': '10', 'cols': '40', }
        if attrs:
            default_attrs.update(attrs)
        super(MarkItUpWidget, self).__init__(default_attrs)
        super().__init__(default_attrs)

    def render(self, name, value, attrs=None, renderer=None):
        if value is None:

M src/wiki/forms.py => src/wiki/forms.py +16 -16
@@ 193,7 193,7 @@ class MoveForm(forms.Form):
                                  required=False)

    def clean(self):
        cd = super(MoveForm, self).clean()
        cd = super().clean()
        if cd.get('slug'):
            dest_path = get_object_or_404(models.URLPath, pk=self.cleaned_data['destination'])
            cd['slug'] = _clean_slug(cd['slug'], dest_path)


@@ 261,7 261,7 @@ class EditForm(forms.Form, SpamProtectionMixin):

            kwargs['initial'] = initial

        super(EditForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)

    def clean_title(self):
        title = self.cleaned_data.get('title', None)


@@ 275,7 275,7 @@ class EditForm(forms.Form, SpamProtectionMixin):
        No new revisions have been created since user attempted to edit
        Revision title or content has changed
        """
        cd = super(EditForm, self).clean()
        cd = super().clean()
        if self.no_clean or self.preview:
            return cd
        if not str(self.initial_revision.id) == str(self.presumed_revision):


@@ 299,10 299,10 @@ class SelectWidgetBootstrap(BuildAttrsCompat, forms.Select):
        attrs['class'] = 'btn-group pull-left btn-group-form'
        self.disabled = disabled
        self.noscript_widget = forms.Select(attrs={}, choices=choices)
        super(SelectWidgetBootstrap, self).__init__(attrs, choices)
        super().__init__(attrs, choices)

    def __setattr__(self, k, value):
        super(SelectWidgetBootstrap, self).__setattr__(k, value)
        super().__setattr__(k, value)
        if k not in ('attrs', 'disabled'):
            self.noscript_widget.__setattr__(k, value)



@@ 361,10 361,10 @@ class TextInputPrepend(forms.TextInput):

    def __init__(self, *args, **kwargs):
        self.prepend = kwargs.pop('prepend', "")
        super(TextInputPrepend, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)

    def render(self, *args, **kwargs):
        html = super(TextInputPrepend, self).render(*args, **kwargs)
        html = super().render(*args, **kwargs)
        return mark_safe(
            '<div class="input-group"><span class="input-group-addon">%s</span>%s</div>' %
            (self.prepend, html))


@@ 373,7 373,7 @@ class TextInputPrepend(forms.TextInput):
class CreateForm(forms.Form, SpamProtectionMixin):

    def __init__(self, request, urlpath_parent, *args, **kwargs):
        super(CreateForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        self.request = request
        self.urlpath_parent = urlpath_parent



@@ 397,7 397,7 @@ class CreateForm(forms.Form, SpamProtectionMixin):
        return _clean_slug(self.cleaned_data['slug'], self.urlpath_parent)

    def clean(self):
        super(CreateForm, self).clean()
        super().clean()
        self.check_spam()
        return self.cleaned_data



@@ 407,7 407,7 @@ class DeleteForm(forms.Form):
    def __init__(self, *args, **kwargs):
        self.article = kwargs.pop('article')
        self.has_children = kwargs.pop('has_children')
        super(DeleteForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)

    confirm = forms.BooleanField(required=False,
                                 label=_('Yes, I am sure'))


@@ 420,7 420,7 @@ class DeleteForm(forms.Form):
                                      widget=HiddenInput(), required=False)

    def clean(self):
        cd = super(DeleteForm, self).clean()
        cd = super().clean()
        if not cd['confirm']:
            raise forms.ValidationError(ugettext('You are not sure enough!'))
        if cd['revision'] != self.article.current_revision:


@@ 481,7 481,7 @@ class PermissionsForm(PluginSettingsFormMixin, forms.ModelForm):
        kwargs['instance'] = article
        kwargs['initial'] = {'locked': article.current_revision.locked}

        super(PermissionsForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)

        self.can_change_groups = False
        self.can_assign = False


@@ 540,7 540,7 @@ class PermissionsForm(PluginSettingsFormMixin, forms.ModelForm):
        return user

    def save(self, commit=True):
        article = super(PermissionsForm, self).save(commit=False)
        article = super().save(commit=False)

        # Alter the owner according to the form field owner_username
        # TODO: Why not rename this field to 'owner' so this happens


@@ 620,7 620,7 @@ class UserCreationForm(UserCreationForm):
    email = forms.EmailField(required=True)

    def __init__(self, *args, **kwargs):
        super(UserCreationForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)

        # Add honeypots
        self.honeypot_fieldnames = "address", "phone"


@@ 638,7 638,7 @@ class UserCreationForm(UserCreationForm):
            )

    def clean(self):
        cd = super(UserCreationForm, self).clean()
        cd = super().clean()
        for fieldname in self.honeypot_fieldnames:
            if cd[fieldname]:
                raise forms.ValidationError(


@@ 655,7 655,7 @@ class UserUpdateForm(forms.ModelForm):
    password2 = forms.CharField(label="Confirm password", widget=forms.PasswordInput(), required=False)

    def clean(self):
        cd = super(UserUpdateForm, self).clean()
        cd = super().clean()
        password1 = cd.get('password1')
        password2 = cd.get('password2')


M src/wiki/models/pluginbase.py => src/wiki/models/pluginbase.py +1 -1
@@ 131,7 131,7 @@ class SimplePlugin(ArticlePlugin):

    def __init__(self, *args, **kwargs):
        article = kwargs.pop('article', None)
        super(SimplePlugin, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        if not self.pk and not article:
            raise SimplePluginCreateError(
                "Keyword argument 'article' expected.")

M src/wiki/models/urlpath.py => src/wiki/models/urlpath.py +2 -2
@@ 182,7 182,7 @@ class URLPath(MPTTModel):
    def delete(self, *args, **kwargs):
        assert not (self.parent and self.get_children()
                    ), "You cannot delete a root article with children."
        super(URLPath, self).delete(*args, **kwargs)
        super().delete(*args, **kwargs)

    class Meta:
        verbose_name = _('URL path')


@@ 203,7 203,7 @@ class URLPath(MPTTModel):
                raise ValidationError(
                    _('There is already a root node on %s') %
                    self.site)
        super(URLPath, self).clean(*args, **kwargs)
        super().clean(*args, **kwargs)

    @classmethod
    def get_by_path(cls, path, select_related=False):

M src/wiki/plugins/attachments/forms.py => src/wiki/plugins/attachments/forms.py +6 -6
@@ 23,7 23,7 @@ class AttachmentForm(forms.ModelForm):
        self.article = kwargs.pop('article', None)
        self.request = kwargs.pop('request', None)
        self.attachment = kwargs.pop('attachment', None)
        super(AttachmentForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)

    def clean_file(self):
        uploaded_file = self.cleaned_data.get('file', None)


@@ 36,7 36,7 @@ class AttachmentForm(forms.ModelForm):

    def save(self, *args, **kwargs):
        commit = kwargs.get('commit', True)
        attachment_revision = super(AttachmentForm, self).save(commit=False)
        attachment_revision = super().save(commit=False)

        # Added because of AttachmentArchiveForm removing file from fields
        # should be more elegant


@@ 85,7 85,7 @@ class AttachmentArchiveForm(AttachmentForm):
        required=False)

    def __init__(self, *args, **kwargs):
        super(AttachmentArchiveForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        ordered_fields = ['unzip_archive', 'file']
        self.fields.keyOrder = ordered_fields + [k
                                                 for k in self.fields.keys()


@@ 104,11 104,11 @@ class AttachmentArchiveForm(AttachmentForm):
            except zipfile.BadZipfile:
                raise forms.ValidationError(ugettext("Not a zip file"))
        else:
            return super(AttachmentArchiveForm, self).clean_file()
            return super().clean_file()
        return uploaded_file

    def clean(self):
        super(AttachmentArchiveForm, self).clean()
        super().clean()
        if not can_moderate(self.article, self.request.user):
            raise forms.ValidationError(
                ugettext("User not allowed to moderate this article"))


@@ 148,7 148,7 @@ class AttachmentArchiveForm(AttachmentForm):
                raise
            return new_attachments
        else:
            return super(AttachmentArchiveForm, self).save(*args, **kwargs)
            return super().save(*args, **kwargs)

    class Meta(AttachmentForm.Meta):
        fields = ['description', ]

M src/wiki/plugins/attachments/views.py => src/wiki/plugins/attachments/views.py +15 -15
@@ 37,7 37,7 @@ class AttachmentView(ArticleMixin, FormView):

        # Fixing some weird transaction issue caused by adding commit_manually
        # to form_valid
        return super(AttachmentView, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def form_valid(self, form):



@@ 65,7 65,7 @@ class AttachmentView(ArticleMixin, FormView):
            article_id=self.article.id)

    def get_form_kwargs(self):
        kwargs = super(AttachmentView, self).get_form_kwargs()
        kwargs = super().get_form_kwargs()
        kwargs['article'] = self.article
        kwargs['request'] = self.request
        return kwargs


@@ 82,7 82,7 @@ class AttachmentView(ArticleMixin, FormView):
        kwargs['search_form'] = forms.SearchForm()
        kwargs['selected_tab'] = 'attachments'
        kwargs['anonymous_disallowed'] = self.request.user.is_anonymous() and not settings.ANONYMOUS
        return super(AttachmentView, self).get_context_data(**kwargs)
        return super().get_context_data(**kwargs)


class AttachmentHistoryView(ArticleMixin, TemplateView):


@@ 101,14 101,14 @@ class AttachmentHistoryView(ArticleMixin, TemplateView):
                models.Attachment.objects.active(),
                id=attachment_id,
                articles=article)
        return super(AttachmentHistoryView, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_context_data(self, **kwargs):
        kwargs['attachment'] = self.attachment
        kwargs['revisions'] = self.attachment.attachmentrevision_set.all().order_by(
            '-revision_number')
        kwargs['selected_tab'] = 'attachments'
        return super(AttachmentHistoryView, self).get_context_data(**kwargs)
        return super().get_context_data(**kwargs)


class AttachmentReplaceView(ArticleMixin, FormView):


@@ 132,7 132,7 @@ class AttachmentReplaceView(ArticleMixin, FormView):
                id=attachment_id,
                articles=article)
            self.can_moderate = False
        return super(AttachmentReplaceView, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_form_class(self):
        if self.can_moderate:


@@ 182,13 182,13 @@ class AttachmentReplaceView(ArticleMixin, FormView):
            article_id=self.article.id)

    def get_form(self, form_class=None):
        form = super(AttachmentReplaceView, self).get_form(form_class=form_class)
        form = super().get_form(form_class=form_class)
        form.fields['file'].help_text = _(
            'Your new file will automatically be renamed to match the file already present. Files with different extensions are not allowed.')
        return form

    def get_form_kwargs(self):
        kwargs = super(AttachmentReplaceView, self).get_form_kwargs()
        kwargs = super().get_form_kwargs()
        kwargs['article'] = self.article
        kwargs['request'] = self.request
        kwargs['attachment'] = self.attachment


@@ 202,7 202,7 @@ class AttachmentReplaceView(ArticleMixin, FormView):
            kwargs['form'] = self.get_form()
        kwargs['attachment'] = self.attachment
        kwargs['selected_tab'] = 'attachments'
        return super(AttachmentReplaceView, self).get_context_data(**kwargs)
        return super().get_context_data(**kwargs)


class AttachmentDownloadView(ArticleMixin, View):


@@ 227,7 227,7 @@ class AttachmentDownloadView(ArticleMixin, View):
                attachment__articles=article)
        else:
            self.revision = self.attachment.current_revision
        return super(AttachmentDownloadView, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        if self.revision:


@@ 266,7 266,7 @@ class AttachmentChangeRevisionView(ArticleMixin, View):
            models.AttachmentRevision,
            id=revision_id,
            attachment__articles=article)
        return super(AttachmentChangeRevisionView, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.attachment.current_revision = self.revision


@@ 297,7 297,7 @@ class AttachmentAddView(ArticleMixin, View):
            models.Attachment.objects.active().can_write(
                request.user),
            id=attachment_id)
        return super(AttachmentAddView, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        if not self.attachment.articles.filter(id=self.article.id):


@@ 329,7 329,7 @@ class AttachmentDeleteView(ArticleMixin, FormView):
        self.attachment = get_object_or_404(models.Attachment, id=attachment_id, articles=article)
        if not self.attachment.can_delete(request.user):
            return response_forbidden(request, article, kwargs.get('urlpath', None))
        return super(AttachmentDeleteView, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def form_valid(self, form):



@@ 359,7 359,7 @@ class AttachmentDeleteView(ArticleMixin, FormView):
        kwargs['selected_tab'] = 'attachments'
        if 'form' not in kwargs:
            kwargs['form'] = self.get_form()
        return super(AttachmentDeleteView, self).get_context_data(**kwargs)
        return super().get_context_data(**kwargs)


class AttachmentSearchView(ArticleMixin, ListView):


@@ 372,7 372,7 @@ class AttachmentSearchView(ArticleMixin, ListView):

    @method_decorator(get_article(can_write=True))
    def dispatch(self, request, article, *args, **kwargs):
        return super(AttachmentSearchView, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_queryset(self):
        self.query = self.request.GET.get('query', None)

M src/wiki/plugins/globalhistory/views.py => src/wiki/plugins/globalhistory/views.py +2 -2
@@ 17,7 17,7 @@ class GlobalHistory(ListView):
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        self.only_last = kwargs.get('only_last', 0)
        return super(GlobalHistory, self).dispatch(
        return super().dispatch(
            request, *args, **kwargs)

    def get_queryset(self):


@@ 29,4 29,4 @@ class GlobalHistory(ListView):

    def get_context_data(self, **kwargs):
        kwargs['only_last'] = self.only_last
        return super(GlobalHistory, self).get_context_data(**kwargs)
        return super().get_context_data(**kwargs)

M src/wiki/plugins/images/admin.py => src/wiki/plugins/images/admin.py +1 -1
@@ 11,7 11,7 @@ class ImageForm(forms.ModelForm):
        exclude = ()

    def __init__(self, *args, **kwargs):
        super(ImageForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        if self.instance.pk:
            revisions = models.ImageRevision.objects.filter(
                plugin=self.instance)

M src/wiki/plugins/images/forms.py => src/wiki/plugins/images/forms.py +6 -6
@@ 10,7 10,7 @@ class SidebarForm(PluginSidebarFormMixin):
    def __init__(self, article, request, *args, **kwargs):
        self.article = article
        self.request = request
        super(SidebarForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        self.fields['image'].required = True

    def get_usermessage(self):


@@ 22,11 22,11 @@ class SidebarForm(PluginSidebarFormMixin):
            image = models.Image()
            image.article = self.article
            kwargs['commit'] = False
            revision = super(SidebarForm, self).save(*args, **kwargs)
            revision = super().save(*args, **kwargs)
            revision.set_from_request(self.request)
            image.add_revision(self.instance, save=True)
            return revision
        return super(SidebarForm, self).save(*args, **kwargs)
        return super().save(*args, **kwargs)

    class Meta:
        model = models.ImageRevision


@@ 38,19 38,19 @@ class RevisionForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.image = kwargs.pop('image')
        self.request = kwargs.pop('request')
        super(RevisionForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        self.fields['image'].required = True

    def save(self, *args, **kwargs):
        if not self.instance.id:
            kwargs['commit'] = False
            revision = super(RevisionForm, self).save(*args, **kwargs)
            revision = super().save(*args, **kwargs)
            revision.inherit_predecessor(self.image, skip_image_file=True)
            revision.deleted = False  # Restore automatically if deleted
            revision.set_from_request(self.request)
            self.image.add_revision(self.instance, save=True)
            return revision
        return super(RevisionForm, self).save(*args, **kwargs)
        return super().save(*args, **kwargs)

    class Meta:
        model = models.ImageRevision

M src/wiki/plugins/images/models.py => src/wiki/plugins/images/models.py +1 -1
@@ 91,7 91,7 @@ class ImageRevision(RevisionPluginRevision):
        be unset if it's the initial history entry.
        """
        predecessor = image.current_revision.imagerevision
        super(ImageRevision, self).inherit_predecessor(image)
        super().inherit_predecessor(image)
        self.plugin = predecessor.plugin
        self.deleted = predecessor.deleted
        self.locked = predecessor.locked

M src/wiki/plugins/images/views.py => src/wiki/plugins/images/views.py +4 -4
@@ 28,7 28,7 @@ class ImageView(ArticleMixin, ListView):

    @method_decorator(get_article(can_read=True, not_locked=True))
    def dispatch(self, request, article, *args, **kwargs):
        return super(ImageView, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_queryset(self):
        if (self.article.can_moderate(self.request.user) or


@@ 93,7 93,7 @@ class PurgeView(ArticleMixin, FormView):
    def dispatch(self, request, article, *args, **kwargs):
        self.image = get_object_or_404(models.Image, article=article,
                                       id=kwargs.get('image_id', None))
        return super(PurgeView, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def form_valid(self, form):



@@ 165,7 165,7 @@ class RevisionAddView(ArticleMixin, FormView):
        return ArticleMixin.dispatch(self, request, article, *args, **kwargs)

    def get_form_kwargs(self, **kwargs):
        kwargs = super(RevisionAddView, self).get_form_kwargs(**kwargs)
        kwargs = super().get_form_kwargs(**kwargs)
        kwargs['image'] = self.image
        kwargs['request'] = self.request
        return kwargs


@@ 175,7 175,7 @@ class RevisionAddView(ArticleMixin, FormView):
        # with the form instance
        if 'form' not in kwargs:
            kwargs['form'] = self.get_form()
        kwargs = super(RevisionAddView, self).get_context_data(**kwargs)
        kwargs = super().get_context_data(**kwargs)
        kwargs['image'] = self.image
        return kwargs


M src/wiki/plugins/notifications/forms.py => src/wiki/plugins/notifications/forms.py +4 -4
@@ 33,7 33,7 @@ class ArticleSubscriptionModelMultipleChoiceField(
class SettingsModelForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(SettingsModelForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        instance = kwargs.get('instance', None)
        self.__editing_instance = False
        if instance:


@@ 60,7 60,7 @@ class SettingsModelForm(forms.ModelForm):
            )

    def save(self, *args, **kwargs):
        instance = super(SettingsModelForm, self).save(*args, **kwargs)
        instance = super().save(*args, **kwargs)
        if self.__editing_instance:
            # Django < 1.5 returns list objects when ModelMultipleChoiceField
            # is empty.. so check before calling delete()


@@ 81,7 81,7 @@ class BaseSettingsFormSet(BaseModelFormSet):

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user')
        super(BaseSettingsFormSet, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)

    def get_queryset(self):
        return Settings.objects.filter(


@@ 152,7 152,7 @@ class SubscriptionForm(PluginSettingsFormMixin, forms.Form):
                'settings': self.default_settings,
            }
        kwargs['initial'] = initial
        super(SubscriptionForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        self.fields['settings'].queryset = Settings.objects.filter(
            user=request.user,
        )

M src/wiki/plugins/notifications/views.py => src/wiki/plugins/notifications/views.py +1 -1
@@ 15,7 15,7 @@ class NotificationSettings(FormView):

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(NotificationSettings, self).dispatch(request, *args, **kwargs)
        return super().dispatch(request, *args, **kwargs)

    def form_valid(self, formset):
        for form in formset:

M src/wiki/views/accounts.py => src/wiki/views/accounts.py +9 -9
@@ 43,10 43,10 @@ class Signup(CreateView):
            c = {'error_msg': _('Account signup is only allowed for administrators.')}
            return render(request, "wiki/error.html", context=c)

        return super(Signup, self).dispatch(request, *args, **kwargs)
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(Signup, self).get_context_data(**kwargs)
        context = super().get_context_data(**kwargs)
        context['honeypot_class'] = context['form'].honeypot_class
        context['honeypot_jsfunction'] = context['form'].honeypot_jsfunction
        return context


@@ 63,7 63,7 @@ class Logout(View):
    def dispatch(self, request, *args, **kwargs):
        if not settings.ACCOUNT_HANDLING:
            return redirect(settings.LOGOUT_URL)
        return super(Logout, self).dispatch(request, *args, **kwargs)
        return super().dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        auth_logout(request)


@@ 81,22 81,22 @@ class Login(FormView):
            return redirect('wiki:root')
        if not settings.ACCOUNT_HANDLING:
            return redirect(settings.LOGIN_URL)
        return super(Login, self).dispatch(request, *args, **kwargs)
        return super().dispatch(request, *args, **kwargs)

    def get_form_kwargs(self):
        self.request.session.set_test_cookie()
        kwargs = super(Login, self).get_form_kwargs()
        kwargs = super().get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

    def post(self, request, *args, **kwargs):
        self.referer = request.session.get('login_referer', '')
        return super(Login, self).post(request, *args, **kwargs)
        return super().post(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        self.referer = request.META.get('HTTP_REFERER', '')
        request.session['login_referer'] = self.referer
        return super(Login, self).get(request, *args, **kwargs)
        return super().get(request, *args, **kwargs)

    def form_valid(self, form, *args, **kwargs):
        auth_login(self.request, form.get_user())


@@ 125,11 125,11 @@ class Update(UpdateView):
        """
        self.referer = request.META.get('HTTP_REFERER', '')
        request.session['login_referer'] = self.referer
        return super(Update, self).get(request, *args, **kwargs)
        return super().get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.referer = request.session.get('login_referer', '')
        return super(Update, self).post(request, *args, **kwargs)
        return super().post(request, *args, **kwargs)

    def form_valid(self, form):
        pw = form.cleaned_data["password1"]

M src/wiki/views/article.py => src/wiki/views/article.py +27 -28
@@ 36,7 36,7 @@ class ArticleView(ArticleMixin, TemplateView):

    @method_decorator(get_article(can_read=True))
    def dispatch(self, request, article, *args, **kwargs):
        return super(ArticleView, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_context_data(self, **kwargs):
        kwargs['selected_tab'] = 'view'


@@ 50,8 50,7 @@ class Create(FormView, ArticleMixin):

    @method_decorator(get_article(can_write=True, can_create=True))
    def dispatch(self, request, article, *args, **kwargs):

        return super(Create, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_form(self, form_class=None):
        """


@@ 158,13 157,13 @@ class Delete(FormView, ArticleMixin):
                else:
                    self.cannot_delete_root = True

        return super(Delete, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_initial(self):
        return {'revision': self.article.current_revision}

    def get_form(self, form_class=None):
        form = super(Delete, self).get_form(form_class=form_class)
        form = super().get_form(form_class=form_class)
        if self.article.can_moderate(self.request.user):
            form.fields['purge'].widget = forms.forms.CheckboxInput()
        return form


@@ 230,7 229,7 @@ class Delete(FormView, ArticleMixin):
        kwargs['delete_children'] = self.children_slice[:20]
        kwargs['delete_children_more'] = len(self.children_slice) > 20
        kwargs['cannot_delete_children'] = cannot_delete_children
        return super(Delete, self).get_context_data(**kwargs)
        return super().get_context_data(**kwargs)


class Edit(ArticleMixin, FormView):


@@ 244,7 243,7 @@ class Edit(ArticleMixin, FormView):
    def dispatch(self, request, article, *args, **kwargs):
        self.sidebar_plugins = plugin_registry.get_sidebar()
        self.sidebar = []
        return super(Edit, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_initial(self):
        initial = FormView.get_initial(self)


@@ 299,7 298,7 @@ class Edit(ArticleMixin, FormView):
            else:
                form = None
            self.sidebar.append((plugin, form))
        return super(Edit, self).get(request, *args, **kwargs)
        return super().get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        # Generate sidebar forms


@@ 350,7 349,7 @@ class Edit(ArticleMixin, FormView):
            else:
                form = None
            self.sidebar.append((plugin, form))
        return super(Edit, self).post(request, *args, **kwargs)
        return super().post(request, *args, **kwargs)

    def form_valid(self, form):
        """Create a new article revision when the edit form is valid


@@ 383,7 382,7 @@ class Edit(ArticleMixin, FormView):
        kwargs['editor'] = editors.getEditor()
        kwargs['selected_tab'] = 'edit'
        kwargs['sidebar'] = self.sidebar
        return super(Edit, self).get_context_data(**kwargs)
        return super().get_context_data(**kwargs)


class Move(ArticleMixin, FormView):


@@ 394,7 393,7 @@ class Move(ArticleMixin, FormView):
    @method_decorator(login_required)
    @method_decorator(get_article(can_write=True, not_locked=True))
    def dispatch(self, request, article, *args, **kwargs):
        return super(Move, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_form(self, form_class=None):
        if form_class is None:


@@ 407,7 406,7 @@ class Move(ArticleMixin, FormView):
            kwargs['form'] = self.get_form()
        kwargs['root_path'] = models.URLPath.root()

        return super(Move, self).get_context_data(**kwargs)
        return super().get_context_data(**kwargs)

    @transaction.atomic
    def form_valid(self, form):


@@ 553,7 552,7 @@ class Deleted(Delete):
                else:
                    return redirect('wiki:get', article_id=article.id)

        return super(Deleted, self).dispatch1(request, article, *args, **kwargs)
        return super().dispatch1(request, article, *args, **kwargs)

    def get_initial(self):
        return {'revision': self.article.current_revision,


@@ 574,7 573,7 @@ class Source(ArticleMixin, TemplateView):

    @method_decorator(get_article(can_read=True))
    def dispatch(self, request, article, *args, **kwargs):
        return super(Source, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_context_data(self, **kwargs):
        kwargs['selected_tab'] = 'source'


@@ 604,7 603,7 @@ class History(ListView, ArticleMixin):

    @method_decorator(get_article(can_read=True))
    def dispatch(self, request, article, *args, **kwargs):
        return super(History, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)


class Dir(ListView, ArticleMixin):


@@ 623,7 622,7 @@ class Dir(ListView, ArticleMixin):
            self.query = self.filter_form.cleaned_data['query']
        else:
            self.query = None
        return super(Dir, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_queryset(self):
        children = self.urlpath.get_children().can_read(self.request.user)


@@ 672,7 671,7 @@ class SearchView(ListView):
            self.query = self.search_form.cleaned_data['q']
        else:
            self.query = None
        return super(SearchView, self).dispatch(request, *args, **kwargs)
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        if not self.query:


@@ 697,7 696,7 @@ class SearchView(ListView):
        return articles.order_by('-current_revision__created')

    def get_context_data(self, **kwargs):
        kwargs = super(SearchView, self).get_context_data(**kwargs)
        kwargs = super().get_context_data(**kwargs)
        kwargs['search_form'] = self.search_form
        kwargs['search_query'] = self.query
        kwargs['urlpath'] = self.urlpath


@@ 722,7 721,7 @@ class Settings(ArticleMixin, TemplateView):
    @method_decorator(login_required)
    @method_decorator(get_article(can_read=True))
    def dispatch(self, request, article, *args, **kwargs):
        return super(Settings, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def get_form_classes(self,):
        """


@@ 762,7 761,7 @@ class Settings(ArticleMixin, TemplateView):
            else:
                form = Form(self.article, self.request)
            self.forms.append(form)
        return super(Settings, self).get(*args, **kwargs)
        return super().get(*args, **kwargs)

    def get(self, *args, **kwargs):
        self.forms = []


@@ 774,7 773,7 @@ class Settings(ArticleMixin, TemplateView):
        for Form in self.get_form_classes():
            self.forms.append(Form(new_article, self.request))

        return super(Settings, self).get(*args, **kwargs)
        return super().get(*args, **kwargs)

    def get_success_url(self):
        if self.urlpath:


@@ 784,7 783,7 @@ class Settings(ArticleMixin, TemplateView):
    def get_context_data(self, **kwargs):
        kwargs['selected_tab'] = 'settings'
        kwargs['forms'] = self.forms
        return super(Settings, self).get_context_data(**kwargs)
        return super().get_context_data(**kwargs)


class ChangeRevisionView(RedirectView):


@@ 797,7 796,7 @@ class ChangeRevisionView(RedirectView):
        self.urlpath = kwargs.pop('kwargs', False)
        self.change_revision()

        return super(ChangeRevisionView, self).dispatch(request, *args, **kwargs)
        return super().dispatch(request, *args, **kwargs)

    def get_redirect_url(self, **kwargs):
        if self.urlpath:


@@ 844,7 843,7 @@ class Preview(ArticleMixin, TemplateView):
            )
        else:
            self.revision = None
        return super(Preview, self).dispatch(request, article, *args, **kwargs)
        return super().dispatch(request, article, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        edit_form = forms.EditForm(request, self.article.current_revision, request.POST, preview=True)


@@ 852,14 851,14 @@ class Preview(ArticleMixin, TemplateView):
            self.title = edit_form.cleaned_data['title']
            self.content = edit_form.cleaned_data['content']
            self.preview = True
        return super(Preview, self).get(request, *args, **kwargs)
        return super().get(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        if self.revision and not self.title:
            self.title = self.revision.title
        if self.revision and not self.content:
            self.content = self.revision.content
        return super(Preview, self).get(request, *args, **kwargs)
        return super().get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        kwargs['title'] = self.title


@@ 984,7 983,7 @@ class CreateRootView(FormView):
            # then it might cascade to delete a lot of things on an existing
            # installation.... / benjaoming
            root.delete()
        return super(CreateRootView, self).dispatch(request, *args, **kwargs)
        return super().dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        models.URLPath.create_root(


@@ 995,7 994,7 @@ class CreateRootView(FormView):
        return redirect("wiki:root")

    def get_context_data(self, **kwargs):
        kwargs = super(CreateRootView, self).get_context_data(**kwargs)
        kwargs = super().get_context_data(**kwargs)
        kwargs['editor'] = editors.getEditor()
        # Needed since Django 1.9 because get_context_data is no longer called
        # with the form instance

M src/wiki/views/deleted_list.py => src/wiki/views/deleted_list.py +2 -2
@@ 12,7 12,7 @@ class DeletedListView(TemplateView):
        if not request.user.is_superuser:
            return redirect('wiki:root')

        return super(DeletedListView, self).dispatch(request, *args, **kwargs)
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        article_list = models.Article.objects.all()


@@ 21,4 21,4 @@ class DeletedListView(TemplateView):
            if(article.current_revision.deleted):
                deleted_articles.append(article)
        kwargs['deleted_articles'] = deleted_articles
        return super(DeletedListView, self).get_context_data(**kwargs)
        return super().get_context_data(**kwargs)

M src/wiki/views/mixins.py => src/wiki/views/mixins.py +1 -1
@@ 30,7 30,7 @@ class ArticleMixin(TemplateResponseMixin):
                    "Attribute error most likely caused by wrong MPTT version. Use 0.5.3+.\n\n" +
                    str(e))
                raise
        return super(ArticleMixin, self).dispatch(request, *args, **kwargs)
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        kwargs['urlpath'] = self.urlpath

M tests/base.py => tests/base.py +4 -4
@@ 18,7 18,7 @@ SUPERUSER1_PASSWORD = 'secret'
class RequireSuperuserMixin(object):

    def setUp(self):
        super(RequireSuperuserMixin, self).setUp()
        super().setUp()

        from django.contrib.auth import get_user_model
        User = get_user_model()


@@ 44,7 44,7 @@ class TestBase(RequireBasicData, TestCase):
class RequireRootArticleMixin(object):

    def setUp(self):
        super(RequireRootArticleMixin, self).setUp()
        super().setUp()
        self.root = URLPath.create_root()
        self.root_article = URLPath.root().article
        rev = self.root_article.current_revision


@@ 62,7 62,7 @@ class ArticleTestBase(RequireRootArticleMixin, TestBase):

class DjangoClientTestBase(TestBase):
    def setUp(self):
        super(DjangoClientTestBase, self).setUp()
        super().setUp()

        self.client.login(username=SUPERUSER1_USERNAME, password=SUPERUSER1_PASSWORD)



@@ 72,7 72,7 @@ class WebTestCommonMixin(RequireBasicData, django_functest.ShortcutLoginMixin):
    Common setup required for WebTest and Selenium tests
    """
    def setUp(self):
        super(WebTestCommonMixin, self).setUp()
        super().setUp()

        self.shortcut_login(username=SUPERUSER1_USERNAME,
                            password=SUPERUSER1_PASSWORD)

M tests/core/test_markdown.py => tests/core/test_markdown.py +1 -1
@@ 43,7 43,7 @@ class ArticleMarkdownTests(ArticleTestBase):
class ResponsiveTableExtensionTests(TestCase):

    def setUp(self):
        super(ResponsiveTableExtensionTests, self).setUp()
        super().setUp()
        self.md = markdown.Markdown(extensions=[
            'extra',
            ResponsiveTableExtension()

M tests/core/test_template_tags.py => tests/core/test_template_tags.py +2 -2
@@ 30,7 30,7 @@ class ArticleForObjectTemplatetagTest(TemplateTestCase):
    """

    def setUp(self):
        super(ArticleForObjectTemplatetagTest, self).setUp()
        super().setUp()
        from wiki.templatetags import wiki_tags
        wiki_tags._cache = {}



@@ 151,7 151,7 @@ class WikiRenderTest(TemplateTestCase):
    def tearDown(self):
        from wiki.core.plugins import registry
        registry._cache = {}
        super(WikiRenderTest, self).tearDown()
        super().tearDown()

    keys = ['article',
            'content',

M tests/plugins/attachments/test_commands.py => tests/plugins/attachments/test_commands.py +2 -2
@@ 14,7 14,7 @@ class TestAttachmentManagementCommands(TestManagementCommands):
    """

    def setUp(self):
        super(TestAttachmentManagementCommands, self).setUp()
        super().setUp()

        self.test_file = tempfile.NamedTemporaryFile('w', delete=False, suffix=".txt")
        self.test_file.write("test")


@@ 32,4 32,4 @@ class TestAttachmentManagementCommands(TestManagementCommands):

    def tearDown(self):
        os.unlink(self.test_file.name)
        super(TestAttachmentManagementCommands, self).tearDown()
        super().tearDown()

M tests/plugins/attachments/test_views.py => tests/plugins/attachments/test_views.py +1 -1
@@ 12,7 12,7 @@ from ...base import RequireRootArticleMixin, ArticleWebTestUtils, DjangoClientTe
class AttachmentTests(RequireRootArticleMixin, ArticleWebTestUtils, DjangoClientTestBase):

    def setUp(self):
        super(AttachmentTests, self).setUp()
        super().setUp()
        self.article = self.root_article
        self.test_data = "This is a plain text file"
        self.test_description = 'My file'

M tests/plugins/images/test_views.py => tests/plugins/images/test_views.py +1 -1
@@ 17,7 17,7 @@ from ...base import (ArticleWebTestUtils, DjangoClientTestBase,
class ImageTests(RequireRootArticleMixin, ArticleWebTestUtils, DjangoClientTestBase):

    def setUp(self):
        super(ImageTests, self).setUp()
        super().setUp()
        self.article = self.root_article
        # A black 1x1 gif
        self.test_data = "R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="