This file is indexed.

/usr/lib/python2.7/dist-packages/maasserver/views/__init__.py is in python-django-maas 1.5.4+bzr2294-0ubuntu1.2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# Copyright 2012 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

"""Views."""

from __future__ import (
    absolute_import,
    print_function,
    unicode_literals,
    )

str = None

__metaclass__ = type
__all__ = [
    "AccountsEdit",
    "AccountsView",
    "HelpfulDeleteView",
    "PaginatedListView",
    "process_form",
    "settings",
    "settings_add_archive",
    "TextTemplateView",
    ]

from abc import (
    ABCMeta,
    abstractmethod,
    )

from django.contrib import messages
from django.http import (
    Http404,
    HttpResponseRedirect,
    )
from django.views.generic import (
    DeleteView,
    ListView,
    TemplateView,
    )


class TextTemplateView(TemplateView):
    """A text-based :class:`django.views.generic.TemplateView`."""

    def render_to_response(self, context, **response_kwargs):
        response_kwargs['content_type'] = 'text/plain'
        return super(
            TemplateView, self).render_to_response(context, **response_kwargs)


class HelpfulDeleteView(DeleteView):
    """Extension to Django's :class:`django.views.generic.DeleteView`.

    This modifies `DeleteView` in a few ways:
     - Deleting a nonexistent object is considered successful.
     - There's a callback that lets you describe the object to the user.
     - User feedback is built in.
     - get_success_url defaults to returning the "next" URL.
     - Confirmation screen also deals nicely with already-deleted object.

    :ivar model: The model class this view is meant to delete.
    """

    __metaclass__ = ABCMeta

    @abstractmethod
    def get_object(self):
        """Retrieve the object to be deleted."""

    @abstractmethod
    def get_next_url(self):
        """URL of page to proceed to after deleting."""

    def delete(self, *args, **kwargs):
        """Delete result of self.get_object(), if any."""
        try:
            self.object = self.get_object()
        except Http404:
            feedback = self.compose_feedback_nonexistent()
        else:
            self.object.delete()
            feedback = self.compose_feedback_deleted(self.object)
        return self.move_on(feedback)

    def get(self, *args, **kwargs):
        """Prompt for confirmation of deletion request in the UI.

        This is where the view acts as a regular template view.

        If the object has been deleted in the meantime though, don't bother:
        we'll just redirect to the next URL and show a notice that the object
        is no longer there.
        """
        try:
            return super(HelpfulDeleteView, self).get(*args, **kwargs)
        except Http404:
            return self.move_on(self.compose_feedback_nonexistent())

    def compose_feedback_nonexistent(self):
        """Compose feedback message: "obj was already deleted"."""
        return "Not deleting: %s not found." % self.model._meta.verbose_name

    def compose_feedback_deleted(self, obj):
        """Compose feedback message: "obj has been deleted"."""
        return ("%s deleted." % self.name_object(obj)).capitalize()

    def name_object(self, obj):
        """Overridable: describe object being deleted to the user.

        The result text will be included in a user notice along the lines of
        "<Object> deleted."

        :param obj: Object that's been deleted from the database.
        :return: Description of the object, along the lines of
            "User <obj.username>".
        """
        return obj._meta.verbose_name

    def show_notice(self, notice):
        """Wrapper for messages.info."""
        messages.info(self.request, notice)

    def move_on(self, feedback_message):
        """Redirect to the post-deletion page, showing the given message."""
        self.show_notice(feedback_message)
        return HttpResponseRedirect(self.get_next_url())


class PaginatedListView(ListView):
    """Paginating extension to :class:`django.views.generic.ListView`

    Adds to the normal list view pagination support by including context
    variables for relative links to other pages, correctly preserving the
    existing query string and path.
    """

    paginate_by = 50

    def _make_page_link(self, page_number):
        """Gives relative url reference to `page_number` from current page

        The return will be one of:
        - A query string including the page number and other params
        - The final path segment if there are no params
        - '.' if there are no params and there is no final path segment

        See RFCs 1808 and 3986 for relative url resolution rules.

        The page number is not checked for sanity, pass only valid pages.
        """
        new_query = self.request.GET.copy()
        if page_number == 1:
            if "page" in new_query:
                del new_query["page"]
        else:
            new_query["page"] = unicode(page_number)
        if not new_query:
            return self.request.path.rsplit("/", 1)[-1] or "."
        return "?" + new_query.urlencode()

    def get_context_data(self, **kwargs):
        """Gives context data also populated with page links

        If already on the first or last page, the same-document reference will
        be given for relative links in that direction, which may be safely
        replaced in the template with a non-anchor element.
        """
        context = super(PaginatedListView, self).get_context_data(**kwargs)
        page_obj = context["page_obj"]
        if page_obj.has_previous():
            context["first_page_link"] = self._make_page_link(1)
            context["previous_page_link"] = self._make_page_link(
                page_obj.previous_page_number())
        else:
            context["first_page_link"] = context["previous_page_link"] = ""
        if page_obj.has_next():
            context["next_page_link"] = self._make_page_link(
                page_obj.next_page_number())
            context["last_page_link"] = self._make_page_link(
                page_obj.paginator.num_pages)
        else:
            context["next_page_link"] = context["last_page_link"] = ""
        return context


def process_form(request, form_class, redirect_url, prefix,
                 success_message=None, form_kwargs=None):
    """Utility method to process subforms (i.e. forms with a prefix).

    :param request: The request which contains the data to be validated.
    :type request: django.http.HttpRequest
    :param form_class: The form class used to perform the validation.
    :type form_class: django.forms.Form
    :param redirect_url: The url where the user should be redirected if the
        form validates successfully.
    :type redirect_url: unicode
    :param prefix: The prefix of the form.
    :type prefix: unicode
    :param success_message: An optional message that will be displayed if the
        form validates successfully.
    :type success_message: unicode
    :param form_kwargs: An optional dict that will passed to the form creation
        method.
    :type form_kwargs: dict or None
    :return: A tuple of the validated form and a response (the response will
        not be None only if the form has been validated correctly).
    :rtype: tuple

    """
    if form_kwargs is None:
        form_kwargs = {}
    if '%s_submit' % prefix in request.POST:
        form = form_class(
            data=request.POST, prefix=prefix, **form_kwargs)
        if form.is_valid():
            if success_message is not None:
                messages.info(request, success_message)
            form.save()
            return form, HttpResponseRedirect(redirect_url)
    else:
        form = form_class(prefix=prefix, **form_kwargs)
    return form, None