diff --git a/fieldset_forms.py b/fieldset_forms.py
index 200fb28..3ee46b6 100644
--- a/fieldset_forms.py
+++ b/fieldset_forms.py
@@ -7,12 +7,16 @@
pass
class FieldsetForm(Form):
- """Extends BaseForm and adds fieldsets and the possibililty to use
- as_div. Inspired by WTForm."""
+ """
+ Extends a standard form and adds fieldsets and the possibililty
+ to use as_div for the automatic rendering of form fields. Inspired
+ by WTForm.
+ """
def __init__(self, *args):
"""Initialize a FormsetField."""
super(FieldsetForm, self).__init__(*args)
+ # check if the user specified the wished layout of the form
if hasattr(self, 'Meta') and hasattr(self.Meta, 'layout'):
msg = "Meta.layout must be iterable"
assert hasattr(self.Meta.layout, '__getitem__'), msg
@@ -29,10 +33,12 @@
return safestring.mark_safe(output)
def create_fieldset(self, field):
- """Create a
around a number of field instances."""
- # field[0] is the name of the fieldset and
- # field[1:] the fields it should include
- # create the divs in each fieldset by calling create_divs
+ """
+ Create a around a number of field instances.
+ field[0] is the name of the fieldset and field[1:] the fields
+ it should include.
+ """
+ # Create the divs in each fieldset by calling create_divs.
return u'%s %s ' % (field[0],
self.create_divs(field[1:]))
@@ -44,7 +50,9 @@
# create a field instance for the bound field
field_instance = self.base_fields[field]
except KeyError:
- # msg on a separate line since the line got too long otherwise
+ # could not create the instance so throw an exception
+ # msg on a separate line since the line got too long
+ # otherwise
msg = "Could not resolve form field '%s'." % field
raise FieldsetError(msg)
# create a bound field containing all the necessary fields
diff --git a/forms.py b/forms.py
index 9e7580e..6e91d84 100644
--- a/forms.py
+++ b/forms.py
@@ -4,7 +4,8 @@
from fieldset_forms import FieldsetForm
class ListNew(FieldsetForm):
- """Form fields to add a new list. Languages are hard coded which should
+ """
+ Form fields to add a new list. Languages are hard coded which should
be replaced by a REST lookup of available languages.
"""
languages = (("Arabic", "Arabic"),
@@ -72,7 +73,8 @@
required = False)
class Meta:
- """Class to handle the automatic insertion of fieldsets and divs.
+ """
+ Class to handle the automatic insertion of fieldsets and divs.
To use it: add a list for each wished fieldset. The first item in
the list should be the wished name of the fieldset, the following
@@ -598,7 +600,7 @@
"topics_enabled", "unsubscribe_policy"]]
class Login(FieldsetForm):
- """Form to let the user log in.
+ """Form fields to let the user log in.
"""
address = forms.EmailField(
label = _('Email address'),
@@ -615,6 +617,10 @@
)
class Meta:
+ """
+ Class to define the name of the fieldsets and what should be
+ included in each.
+ """
layout = [["Login", "address", "password"],]
class ListMassSubscription(FieldsetForm):
@@ -626,4 +632,8 @@
)
class Meta:
+ """
+ Class to define the name of the fieldsets and what should be
+ included in each.
+ """
layout = [["Mass subscription", "emails"],]
diff --git a/mockdata.py b/mockdata.py
index fc77faf..033dc10 100644
--- a/mockdata.py
+++ b/mockdata.py
@@ -1,26 +1,38 @@
# -*- coding: utf-8 -*-
def check_http_method(fn):
- """Decorator function to return a mock response if the requested method was
- PUT or PATCH.
+ """
+ Decorator function to return a mock response if the requested
+ method was PUT or PATCH. Will be removed once this functionality
+ is implemented in the REST server.
"""
def http_req(*kwargs):
if 'method' in kwargs:
+ # If one of the not implemented methods gets called, return
+ # a response saying everything went well (200).
if method.upper() == 'PUT':
return 200
elif method.upper() == 'PATCH':
return 200
else:
+ # otherwise we return the function to let it perform its
+ # usual job
return fn(*kwargs)
-
return http_req
def add_mock_data(cls):
- """Decorator function to add mock data from the database to a list.
+ """
+ Decorator function to add mock data from the database to a list.
+ Once the functionality exists in the REST server this function can
+ be removed.
"""
cls.__orig__init__ = cls.__init__
def __init__(self, *args, **kwargs):
+ """
+ Initiate the list with the missing information and call the
+ usual init function to get the real data already available.
+ """
cls.__orig__init__(self, *args, **kwargs)
self.info['id'] = 9
#self.info['list_name'] = 'List name lorem ipsum dolor sit'
@@ -116,4 +128,3 @@
cls.__init__ = __init__
return cls
-
diff --git a/views.py b/views.py
index cc4b56e..abd5dcf 100644
--- a/views.py
+++ b/views.py
@@ -9,10 +9,21 @@
from forms import *
def login_required(fn):
- """Function (decorator) letting the user log in.
+ """
+ Function (decorator) making sure the user has to log in before
+ they can continue.
+ To use it, add @login_required above the function that requires a
+ user to be logged in. The function requiring login will
+ automatically be added as an argument in the call.
"""
def _login_decorator(*request, **kwargs):
- """Inner decorator to login.
+ """
+ Inner decorator to require a user to login. This inner
+ function gets access to the arguments of the function demanding
+ login to be processed.
+ The function checks that a valid user name and password has
+ been provided and when this is the case the user gets
+ redirected to the original function.
"""
# If the user is already logged in, let them continue directly.
try:
@@ -24,7 +35,7 @@
# Authenticate the user
# This is just a mockup since the authenticate functionality in
# the rest server is still missing.
- # TODO Anna 2010-08-04: implement real authenticate when possible
+ # TODO: implement real authenticate when possible
valid_users = {"james@example.com": "james",
"katie@example.com": "katie",
"kevin@example.com": "kevin"}
@@ -33,6 +44,7 @@
if form.is_valid():
if request[0].POST["address"] in valid_users.keys():
if request[0].POST["password"] == valid_users[request[0].POST["address"]]:
+ # TODO: change this to a better id when possible
request[0].session['member_id'] = request[0].POST["address"]
# make sure to "reset" the method before continuing
request[0].method = 'GET'
@@ -40,12 +52,20 @@
message = "Your username and password didn't match."
else:
message = ""
- return render_to_response(template, {'form': Login(), 'message': message})
+ return render_to_response(template, {'form': Login(),
+ 'message': message})
return _login_decorator
@login_required
def list_new(request, template = 'mailman-django/lists/new.html'):
- """Show or process form to add a new mailing list.
+ """
+ Add a new mailing list.
+ If the request to the function is a GET request an empty form for
+ creating a new list will be displayed. If the request method is
+ POST the form will be evaluated. If the form is considered
+ correct the list gets created and otherwise the form with the data
+ filled in before the last POST request is returned. The user must
+ be logged in to create a new list.
"""
if request.method == 'POST':
form = ListNew(request.POST)
@@ -58,16 +78,17 @@
parts = listname.split('@')
domain = c.get_domain(parts[1])
- if domain.info == 404: # failed to get domain so try creating one
+ if domain.info == 404: # failed to get domain so try
+ # creating a new one
try:
domain = c.create_domain(parts[1])
except MailmanRESTClientError, e:
- # I don't think this error can ever appear... -- Anna
+ # I don't think this error can ever appear. -- Anna
return HttpResponse(e)
try:
response = domain.create_list(parts[0])
return render_to_response('mailman-django/lists/created.html',
- {'fqdn_listname': response.info['fqdn_listname'] })
+ {'fqdn_listname': response.info['fqdn_listname']})
except MailmanRESTClientError, e:
return HttpResponse(e)
@@ -96,7 +117,11 @@
def list_info(request, fqdn_listname = None,
template = 'mailman-django/lists/info.html'):
- """Display list info and/or subscribe or unsubscribe a user to a list.
+ """
+ Display the information there is available for a list. This
+ function also enables subscribing or unsubscribing a user to a
+ list. For the latter two different forms are available for the
+ user to fill in which are evaluated in this function.
"""
try:
c = MailmanRESTClient('localhost:8001')
@@ -105,6 +130,8 @@
return HttpResponse(e)
if request.method == 'POST':
form = False
+ # The form enables both subscribe and unsubscribe. As a result
+ # we must find out which was the case.
action = request.POST.get('name', '')
if action == "subscribe":
form = ListSubscribe(request.POST)
@@ -116,19 +143,24 @@
if action == "subscribe":
real_name = form.cleaned_data.get('real_name', '')
try:
+ # the form was valid so try to subscribe the user
response = the_list.subscribe(address=email,
real_name=real_name)
return HttpResponseRedirect(reverse('list_index'))
except Exception, e:
return HttpResponse(e)
elif action == "unsubscribe":
+ # the form was valid so try to unsubscribe the user
try:
response = the_list.unsubscribe(address=email)
- return render_to_response('mailman-django/lists/unsubscribed.html',
+ template = 'mailman-django/lists/unsubscribed.html'
+ return render_to_response(template,
{'listname': fqdn_listname})
except Exception, e:
return HttpResponse(e)
else:
+ # the user tried to post an incorrect form so make sure we
+ # return the filled in values and let the user try again.
if action == "subscribe":
subscribe = ListSubscribe(request.POST)
unsubscribe = ListUnsubscribe(initial = {'listname': fqdn_listname,
@@ -138,13 +170,14 @@
'name' : 'subscribe'})
unsubscribe = ListUnsubscribe(request.POST)
else:
+ # the request was a GET request so set the two forms to empty
+ # forms
subscribe = ListSubscribe(initial = {'listname': fqdn_listname,
'name' : 'subscribe'})
unsubscribe = ListUnsubscribe(initial = {'listname': fqdn_listname,
'name' : 'unsubscribe'})
listinfo = c.get_list(fqdn_listname)
-
return render_to_response(template, {'subscribe': subscribe,
'unsubscribe': unsubscribe,
'fqdn_listname': fqdn_listname,
@@ -152,8 +185,10 @@
def list_delete(request, fqdn_listname = None,
template = 'mailman-django/lists/index.html'):
- """Delete a list.
"""
+ Delete a list by providing the full list name including domain.
+ """
+
# create a connection to Mailman and get the list
try:
c = MailmanRESTClient('localhost:8001')
@@ -175,7 +210,11 @@
@login_required
def list_settings(request, fqdn_listname = None,
template = 'mailman-django/lists/settings.html'):
- """The settings of a list."""
+ """
+ View and edit the settings of a list.
+ The function requires the user to be logged in and have the
+ permissions necessary to perform the action.
+ """
message = ""
try:
c = MailmanRESTClient('localhost:8001')
@@ -196,7 +235,11 @@
@login_required
def mass_subscribe(request, fqdn_listname = None,
template = 'mailman-django/lists/mass_subscribe.html'):
- """Mass subscribe users to a list."""
+ """
+ Mass subscribe users to a list.
+ This functions is part of the settings for a list and requires the
+ user to be logged in to perform the action.
+ """
message = ""
try:
c = MailmanRESTClient('localhost:8001')
@@ -207,6 +250,8 @@
form = ListMassSubscription(request.POST)
if form.is_valid():
try:
+ # The emails to subscribe should each be provided on a
+ # separate line so get each of them.
emails = request.POST["emails"].splitlines()
message = "The mass subscription was successful."
for email in emails:
@@ -215,17 +260,26 @@
if len(parts) == 2 and '.' in parts[1]:
the_list.subscribe(address=email, real_name="")
else:
+ # At least one email address wasn't valid so
+ # overwrite the success message and ask them to
+ # try again.
message = "Please enter valid email addresses."
except Exception, e:
return HttpResponse(e)
else:
+ # A request to view the page was send so return the form to
+ # mass subscribe users.
form = ListMassSubscription()
return render_to_response(template, {'form': form,
'message': message,
'fqdn_listname': the_list.info['fqdn_listname']})
def logout(request):
- """Let the user logout.
+ """
+ Let the user logout.
+ Some functions requires the user to be logged in to perform the
+ actions. After the user is done, logging out is possible to avoid
+ others having rights they should not have.
"""
try:
del request.session['member_id']