Commits

Luke Plant committed d466083 Merge

Merged from default

  • Participants
  • Parent commits 2a0f029, 808cc71
  • Branches live

Comments (0)

Files changed (36)

File ENV

-workon cciw
-export DJANGO_SETTINGS_MODULE=cciw.settings

File cciw/cciwmain/admin.py

 from cciw.cciwmain.models import Site, Person, Camp
 from django.contrib import admin
 
+
+from functools import wraps
+def rename_app_list(func):
+    m = {'Cciwmain': 'Camp info',
+         'Sitecontent': 'Site content',
+         'Sites': 'Web sites'
+         }
+    @wraps(func)
+    def _wrapper(*args, **kwargs):
+        response = func(*args, **kwargs)
+        app_list = response.context_data.get('app_list')
+        if app_list is not None:
+            for a in app_list:
+                name = a['name']
+                a['name'] = m.get(name, name)
+        title = response.context_data.get('title')
+        if title is not None:
+            app_label = title.split(' ')[0]
+            if app_label in m:
+                response.context_data['title'] = "%s administration" % m[app_label]
+        return response
+    return _wrapper
+
+admin.site.index = rename_app_list(admin.site.index)
+admin.site.app_index = rename_app_list(admin.site.app_index)
+
+
 class SiteAdmin(admin.ModelAdmin):
     fieldsets = (
         (None, {'fields': ('short_name', 'long_name', 'info')}),

File cciw/cciwmain/common.py

 """
 import datetime
 import re
-import urllib
 
 from django.conf import settings
 from django.contrib.sites.models import Site
             l.isCurrentSection = True
 
     context['menulinks'] = links
+    context['GOOGLE_ANALYTICS_ACCOUNT'] = getattr(settings, 'GOOGLE_ANALYTICS_ACCOUNT', '')
 
     return context
 

File cciw/cciwmain/decorators.py

 from django.http import HttpResponse, HttpResponseRedirect
-from django import template
 from django.shortcuts import render
 from django.core.mail import mail_admins
 

File cciw/cciwmain/feeds.py

 from django.contrib.syndication import views as feed_views
-from django.http import Http404, HttpResponse
 from django.utils.feedgenerator import Atom1Feed
 
 MEMBER_FEED_MAX_ITEMS = 20

File cciw/cciwmain/templatetags/bbcode.py

     def __init__(self, repl_dict):
         # "compile" replacement dictionary
 
-        # assume char to char mapping
-        charmap = map(chr, range(256))
-        for k, v in repl_dict.items():
-            if len(k) != 1 or len(v) != 1:
-                self.charmap = None
-                break
-            charmap[ord(k)] = v
-        else:
-            self.charmap = string.join(charmap, u"")
-            return
-
         # string to string mapping; use a regular expression
         keys = repl_dict.keys()
         keys.sort() # lexical order
 
     def replace(self, str):
         # apply replacement dictionary to string
-        if self.charmap:
-            return string.translate(str, self.charmap)
         def repl(match, get=self.dict.get):
             item = match.group(0)
             return get(item, item)
         Renders a node of this BBTag as HTML.
         node is the node to render.
         """
-        raise NotImplementedException()
+        raise NotImplemented()
 
     def render_node_bbcode(self, node):
         opening = self.name # opening tag

File cciw/cciwmain/templatetags/standardpage.py

-from django.utils.http import urlquote, urlencode
 from django import template
 from cciw.sitecontent.models import HtmlChunk
-from cciw.forums.models import Member, Post, Topic, Photo
-from cciw.cciwmain.common import standard_subs, get_current_domain
+from cciw.cciwmain.common import standard_subs
 from cciw.cciwmain.utils import obfuscate_email
-from cciw.middleware.threadlocals import get_current_member
-from django.utils.html import escape
 from django.conf import settings
 
 class EmailNode(template.Node):
         title = context.get('atom_feed_title', None)
         if title:
             thisurl = context['request'].path
-            thisfullurl = 'https://%s%s' % (get_current_domain(), thisurl)
             return (u'<a class="atomlink" href="%(atomurl)s" rel="external" title="%(atomtitle)s" >' +
                     u' <img src="%(atomimgurl)s" alt="Feed icon" /></a> |') \
             % dict(atomurl="%s?format=atom" % thisurl,

File cciw/cciwmain/tests/bbcode.py

 # -*- coding: utf-8 -*-
-import sys
-import os
-
 from django.utils import unittest
 
 from cciw.cciwmain.common import get_member_link

File cciw/cciwmain/tests/decorators.py

-from BeautifulSoup import BeautifulSoup
 from django.test import TestCase
 from cciw.cciwmain.tests.client import CciwClient
 from cciw.cciwmain.tests.forums import CreatePollPage, ADD_POLL_URL
         r = self.client.get(ADD_POLL_URL)
         self.assertTrue(LOGIN_FORM_KEY not in r.content, "Should not get a login form.")
 
-    def test_get_anonymous_produces_redirect(self):
-        """Ensure that when we start with a GET request and have to log in, the user ultimately receives a 'GET' request, not a 'POST' to the view"""
-        r = self.client.get(ADD_POLL_URL)
+    def test_post_produces_redirect(self):
+        """Ensure that when we start with a POST request and have to log in, we get a redirect to the view."""
 
         data = self.client.get_member_login_data(members.TEST_POLL_CREATOR_USERNAME,
                                                  members.TEST_POLL_CREATOR_PASSWORD)
-        r2 = self.client.post(ADD_POLL_URL, data=data)
+        r = self.client.post(ADD_POLL_URL, data=data)
 
         # should be back at orignal page.
-        self.assertTrue(LOGIN_FORM_KEY not in r2.content, "Should not get a login form.")
-        self.assertEqual(r2.status_code, 302)
+        self.assertTrue(LOGIN_FORM_KEY not in r.content, "Should not get a login form.")
+        self.assertEqual(r.status_code, 302)
 
-    def test_post_produces_redirect(self):
-        """Ensure that when we start with a POST request and have to log in, we get a redirect to the view."""
-
-        orig_data = {'some':'random_data', 'details':'dont matter'}
-        r = self.client.post(ADD_POLL_URL, data=orig_data)
-
-        data = self.client.get_member_login_data(members.TEST_POLL_CREATOR_USERNAME,
-                                                 members.TEST_POLL_CREATOR_PASSWORD)
-        r2 = self.client.post(ADD_POLL_URL, data=data)
-
-        # should be back at orignal page.
-        self.assertTrue(LOGIN_FORM_KEY not in r2.content, "Should not get a login form.")
-        self.assertEqual(r2.status_code, 302)
-

File cciw/cciwmain/tests/forums.py

 from cciw.cciwmain.tests.utils import init_query_caches, FuzzyInt
 from cciw.forums.views import forums as forums_views
 from django.core.urlresolvers import reverse
-from datetime import datetime
 from cciw.cciwmain import decorators
 
 FORUM_1_YEAR = 2000
         assert num > settings.FORUM_PAGINATE_TOPICS_BY
         for i in xrange(num):
             topic = Topic.create_topic(member, "Topic %s" % i, self.forum)
-            post = Post.create_post(member, "Message %s" % i, topic, None)
+            Post.create_post(member, "Message %s" % i, topic, None)
 
         request = self.factory.get(self.forum.get_absolute_url())
         with self.assertNumQueries(FuzzyInt(1, 5)):
         assert settings.FORUM_PAGINATE_TOPICS_BY < num
         for i in xrange(num):
             topic = Topic.create_topic(member, "Topic %s" % i, self.forum)
-            post = Post.create_post(member, "Message %s" % i, topic, None)
+            Post.create_post(member, "Message %s" % i, topic, None)
 
         request = self.factory.get(self.path())
         with self.assertNumQueries(FuzzyInt(3, 4)):
         member = Member.objects.get(user_name=TEST_MEMBER_USERNAME)
         # Make sure we have lots of posts
         for i in xrange(100):
-            post = Post.create_post(member, "Message %s" % i, topic=self.topic)
+            Post.create_post(member, "Message %s" % i, topic=self.topic)
 
         init_query_caches()
 
         # Make sure we have lots of topics
         for i in xrange(100):
             photo = Photo.create_default_photo("2000-1-myphoto-%s" % i, self.gallery)
-            post = Post.create_post(member, "A message %s" % i, photo=photo)
+            Post.create_post(member, "A message %s" % i, photo=photo)
 
         request = self.factory.get(self.gallery.get_absolute_url())
         with self.assertNumQueries(3):
         member = Member.objects.get(user_name=TEST_MEMBER_USERNAME)
         # Make sure we have lots of posts
         for i in xrange(100):
-            post = Post.create_post(member, "Message %s" % i, photo=self.photo)
+            Post.create_post(member, "Message %s" % i, photo=self.photo)
 
         request = self.factory.get(self.photo.get_absolute_url())
         with self.assertNumQueries(5):
         assert settings.FORUM_PAGINATE_POSTS_BY < num
         for i in xrange(num):
             topic = Topic.create_topic(member, "Topic %s" % i, self.forum)
-            post = Post.create_post(member, "Message %s" % i, topic=topic)
+            Post.create_post(member, "Message %s" % i, topic=topic)
 
         request = self.factory.get(self.path())
         with self.assertNumQueries(FuzzyInt(1, 4)):
         assert settings.FORUM_PAGINATE_POSTS_BY < num
         for i in xrange(num):
             photo = Photo.create_default_photo("2000-1-a-photo-%s" % i, self.gallery)
-            post = Post.create_post(member, "Message %s" % i, photo=photo)
+            Post.create_post(member, "Message %s" % i, photo=photo)
 
         request = self.factory.get(self.path())
         with self.assertNumQueries(FuzzyInt(1, 3)):

File cciw/cciwmain/tests/members.py

 import glob
 import os
 import re
-import urllib
 
 from BeautifulSoup import BeautifulSoup
 from django.conf import settings
 from django.core.urlresolvers import reverse
 from django.test import TestCase
 from twill import commands as tc
-from twill.shell import TwillCommandLoop
-import twill
 
 from cciw.forums.models import Member, Message
 from cciw.cciwmain.tests.client import CciwClient, RequestFactory
 from cciw.cciwmain.tests.mailhelpers import read_email_url
 from cciw.cciwmain.tests.utils import init_query_caches, FuzzyInt
 from cciw.utils.tests.twillhelpers import TwillMixin, make_twill_url
-import cciw.cciwmain.decorators
 
 
 # created by fixture
         return resp
 
     def test_upload_bad_icon(self):
-        resp = self._assert_icon_upload_fails("badicon.png")
+        self._assert_icon_upload_fails("badicon.png")
 
     def test_upload_outsize_icon(self):
         resp = self._assert_icon_upload_fails("outsize_icon.png")
 
     def test_archive_message_from_inbox(self):
         # Setup
-        msg = self._send_message("A quick message")
-        msg2 = self._send_message("Another message")
+        self._send_message("A quick message")
+        self._send_message("Another message")
         inbox_count = self._inbox_count()
         archived_count = self._archived_count()
 
 
     def test_delete_message_from_inbox(self):
         # Setup
-        msg = self._send_message("A quick message")
+        self._send_message("A quick message")
         inbox_count = self._inbox_count()
         # Get page
         resp = self._get_inbox()

File cciw/cciwmain/tests/news.py

             topic = Topic.create_topic(member, "Topic %s" % i, forum)
             topic.news_item = news_item
             topic.save()
-            post = Post.create_post(member, "Message %s" % i, topic, None)
+            Post.create_post(member, "Message %s" % i, topic, None)
 
         request = factory.get(path)
         with self.assertNumQueries(FuzzyInt(1, 5)):

File cciw/cciwmain/utils.py

 
 For CCIW specific utilities see cciw.cciwmain.common
 """
-import datetime
 import operator
+
 from django.utils.safestring import mark_safe
 from django.utils import simplejson
 from django.utils.functional import Promise
 from django.utils.encoding import force_unicode
-from django.http import HttpResponse
 
 def obfuscate_email(email):
     safe_email = email.replace('@', ' <b>at</b> ').replace('.', ' <b>dot</b> ')
         text = text.replace(chr(i), '')
     return text
 
-def validate_xml(filename):
-    from xml.sax import sax2exts
-    from xml.dom.ext.reader import Sax2
-
-    p = sax2exts.XMLValParserFactory.make_parser()
-    reader = Sax2.Reader(parser=p)
-    dom_object = reader.fromUri(filename)
-    return True
-
 def unslugify(slug):
     "Turns dashes and underscores into spaces and applies title casing"
     return slug.replace("-", " ").replace("_", " ").title()

File cciw/cciwmain/views/camps.py

 import datetime
 
 from django.shortcuts import render
-from django.http import HttpResponse, Http404, HttpResponseRedirect
-from django.conf import settings
+from django.http import Http404
 
 from cciw.cciwmain.models import Camp
 from cciw.forums.models import Forum, Gallery, Photo
 from cciw.forums.views import forums as forums_views
 from cciw.cciwmain.common import create_breadcrumb, get_thisyear, standard_subs
-from cciw.cciwmain.decorators import member_required
-from cciw.cciwmain.templatetags import bbcode
-from cciw.sitecontent.models import HtmlChunk
 import cciw.cciwmain.utils as utils
 
 
 def oldcampphoto(request, year, galleryname, photonumber):
     # Do need to check the gallery exists, just for checking the URL
     try:
-        gallery = Gallery.objects.get(location= 'camps/%s/%s/photos/' % (year, galleryname))
+        Gallery.objects.get(location= 'camps/%s/%s/photos/' % (year, galleryname))
     except Gallery.DoesNotExist:
         raise Http404
 

File cciw/cciwmain/views/misc.py

 
 from cciw.cciwmain.common import get_thisyear, AjaxyFormView, DefaultMetaData
 from cciw.cciwmain.forms import CciwFormMixin
-from cciw.cciwmain import utils
 
 def send_feedback(email, name, message):
     message = wrap(message, 70)

File cciw/forums/anonymizers.py

 from cciw.forums.models import Member, PersonalAward, Message, Poll, PollOption, NewsItem, Topic, Photo, Post
 from anonymizer import Anonymizer
+from mailer import models as mailer_models
 
 class MemberAnonymizer(Anonymizer):
 

File cciw/forums/models.py

 from datetime import datetime, timedelta
 import operator
-import os
+import random
 import re
 
-
 from django.conf import settings
 from django.contrib.auth.models import User
 from django.core import mail
 
 from cciw.cciwmain import common
 from cciw.middleware import threadlocals
-import cciw.middleware.threadlocals as threadlocals
-
 
 # regex used to match forums that belong to camps
 _camp_forum_re = re.compile('^' + settings.CAMP_FORUM_RE + '$')
 
     @staticmethod
     def generate_salt():
-        import random, datetime
         rand64= "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-        random.seed(datetime.datetime.today().microsecond)
+        random.seed(datetime.now().microsecond)
         return rand64[int(random.random()*64)] + rand64[int(random.random()*64)]
 
     @staticmethod
     def is_parent_visible(self):
         if self.topic_id is not None:
             try:
-                topic = self.topic
-                return True
+                return not self.topic.hidden
             except Topic.DoesNotExist:
                 return False
         elif self.photo_id is not None:
             try:
-                photo = self.photo
-                return True
+                return not self.photo.hidden
             except Photo.DoesNotExist:
                 return False
         else:

File cciw/forums/views/forums.py

-from datetime import datetime, date
+from datetime import datetime
 import string
 
 from django.views.generic.edit import ModelFormMixin
 from django.forms import widgets
 from django.shortcuts import get_object_or_404
 from django.utils.safestring import mark_safe
-from django.views.generic.list import ListView
 
-from cciw.forums.models import Forum, Topic, Photo, Post, Member, VoteInfo, NewsItem, Permission, Poll, PollOption, Award
+from cciw.forums.models import Forum, Topic, Photo, Post, VoteInfo, NewsItem, Permission, Poll, PollOption
 from cciw.cciwmain.common import create_breadcrumb, get_order_option, object_list, DefaultMetaData, AjaxyFormView
 from cciw.middleware.threadlocals import get_current_member
 from cciw.cciwmain.decorators import login_redirect
-from django.utils.html import escape
-from cciw.cciwmain import utils
 from cciw.cciwmain.templatetags import bbcode
 from cciw.cciwmain.decorators import member_required, member_required_for_post
 from cciw.cciwmain import feeds
         if not errors:
             if request.POST.has_key('post'):
                 topic = Topic.create_topic(cur_member, subject, forum)
-                post = Post.create_post(cur_member, msg_text, topic, None)
+                Post.create_post(cur_member, msg_text, topic, None)
                 return HttpResponseRedirect('../%s/' % topic.id)
             else:
                 context['preview'] = mark_safe(bbcode.bb2xhtml(msg_text))

File cciw/forums/views/memberadmin.py

 from django.shortcuts import render
 from django.core import mail
 from django.contrib import messages
-from django.contrib.sites.models import Site
 from django.conf import settings
 from django.core.urlresolvers import reverse
 from django.core.validators import email_re

File cciw/mail/lists.py

                     address_for_camp_leaders(camp),
                     address_for_camp_leaders_year(camp.year)]:
         try:
-            email = s.create_email(address, settings.LIST_MAILBOX_NAME)
+            s.create_email(address, settings.LIST_MAILBOX_NAME)
         except xmlrpclib.Fault, e:
             if e.faultString == 'username: Value already exists':
                 pass

File cciw/middleware/http.py

-from django.http import HttpResponsePermanentRedirect
-
 
 class WebFactionFixes(object):
     """

File cciw/officers/applications.py

 
 # To enable Applications to be shared between camps, and in some cases to belong
 # to no camps, there is no direct connection between a Camp and an Application.
-# This means we need another way to do it, and we're using dates.
+# This means we need another way to associate them. We also need to have a
+# concept of 'this year', so that an officer submits once application form 'per
+# year'. To manage this logic we're using dates of camps (which are clustered in
+# the summer) and the invitations to camp that ab officer has.
 
 # Logic for dates:
 # - an application is considered valid for a camp/year if the date_submitted
 #   - is within 12 months of the start date of the camp/first camp that year
 #   - is after the previous year's camps' end dates.
+#
+# i.e. we assume all camps happen in a cluster, and application forms are
+# submitted in the period leading up to that cluster.
 
 def thisyears_applications(user):
     """
     Returns a QuerySet containing the applications a user has that
     apply to 'this year', i.e. to camps still in the future.
     """
-    from cciw.officers.models import Camp
     future_camps = Camp.objects.filter(start_date__gte=datetime.date.today())
     apps = user.application_set.all()
     future_camp = None

File cciw/officers/email.py

 import datetime
+import urllib
 
 from cciw.cciwmain import common
 from cciw.officers.applications import application_to_text, application_to_rtf, application_rtf_filename, application_difference, camps_for_application
 from django.core.mail import send_mail, EmailMessage
 from django.core.urlresolvers import reverse
 from django.utils.crypto import salted_hmac
-import cciw.middleware.threadlocals as threadlocals
-import urllib
+
 
 
 def make_update_email_hash(oldemail, newemail):

File cciw/officers/models.py

         verbose_name = "CRB form log"
         verbose_name_plural = "CRB form logs"
 
-import cciw.officers.admin

File cciw/officers/references.py

 """
 Utilities for dealing with ReferenceForm and Reference
 """
-from django.template.loader import render_to_string
 from django import template
 
 

File cciw/officers/templatetags/reference_utils.py

 from django import template
 from django.template.defaultfilters import stringfilter
-from django.utils.safestring import mark_safe
-from django.utils.html import escape
 
 register = template.Library()
 

File cciw/officers/tests/applicationform.py

 from cciw.officers.models import Application
 from cciw.officers.applications import application_difference
 from cciw.officers.tests.references import OFFICER, LEADER
-from cciw.utils.tests.twillhelpers import TwillMixin, make_django_url, make_twill_url
+from cciw.utils.tests.twillhelpers import TwillMixin, make_django_url
 
 class ApplicationFormView(TwillMixin, TestCase):
     fixtures = ['basic.json', 'officers_users.json']
         self.assertEqual(len(mail.outbox), 0)
         self._twill_login(OFFICER)
         # An old, unfinished application form
-        a_old = self._add_application()
+        self._add_application()
         a = self._add_application()
         tc.go(self._application_edit_url(a.id))
         tc.code(200)

File cciw/officers/tests/applications.py

         self.assertNotContains(resp, self._edit_button)
 
     def test_finished_application(self):
-        app = self.user.application_set.create(finished=True,
-                                               date_submitted=datetime.date.today())
-        resp = self.client.get(self.url)
-        self.assertContains(resp, self._create_button)
-
-    def test_finished_application(self):
-        app = self.user.application_set.create(finished=True,
-                                               date_submitted=datetime.date.today()
-                                               - datetime.timedelta(365))
+        self.user.application_set.create(finished=True,
+                                         date_submitted=datetime.date.today()
+                                         - datetime.timedelta(365))
         resp = self.client.get(self.url)
         self.assertContains(resp, self._create_button)
 
     def test_finished_application_recent(self):
-        app = self.user.application_set.create(finished=True,
-                                               date_submitted=datetime.date.today())
+        self.user.application_set.create(finished=True,
+                                         date_submitted=datetime.date.today())
         resp = self.client.get(self.url)
         self.assertNotContains(resp, self._create_button)
 
     def test_unfinished_application(self):
-        app = self.user.application_set.create(finished=False,
-                                               date_submitted=datetime.date.today())
+        self.user.application_set.create(finished=False,
+                                         date_submitted=datetime.date.today())
         resp = self.client.get(self.url)
         self.assertContains(resp, self._edit_button)
 
     def test_create(self):
-        app = self.user.application_set.create(finished=True,
-                                               date_submitted=datetime.date.today() - datetime.timedelta(365))
+        self.user.application_set.create(finished=True,
+                                         date_submitted=datetime.date.today() - datetime.timedelta(365))
         resp = self.client.post(self.url, {'new':'Create'})
         self.assertEqual(302, resp.status_code)
         self.assertEqual(len(self.user.application_set.all()), 2)

File cciw/officers/views.py

 import datetime
-import itertools
 import operator
 
 from django import forms
 from django.conf import settings
 from django.contrib.admin.views.decorators import staff_member_required
-from django.contrib.admin import widgets
 from django.contrib.auth.decorators import user_passes_test
 from django.contrib.auth.models import User
 from django.contrib import messages
 from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
 from django.core.urlresolvers import reverse
-from django.db import models
 from django.core.validators import email_re
 from django.http import Http404, HttpResponseRedirect, HttpResponse
 from django.shortcuts import render, get_object_or_404
 from cciw.officers.email import make_update_email_hash, send_reference_request_email, make_ref_form_url, make_ref_form_url_hash, send_leaders_reference_email, send_nag_by_officer, send_crb_consent_problem_email
 from cciw.officers.widgets import ExplicitBooleanFieldSelect
 from cciw.officers.models import Application, Reference, ReferenceForm, Invitation, CRBApplication, CRBFormLog
-from cciw.officers.utils import camp_officer_list, camp_slacker_list
+from cciw.officers.utils import camp_slacker_list
 from cciw.officers.references import reference_form_info
 from cciw.utils.views import close_window_response
 from securedownload.views import access_folder_securely
 def _get_camp_or_404(year, number):
     try:
         return Camp.objects.get(year=int(year), number=int(number))
-    except Camp.DoesNotExist, ValueError:
+    except (Camp.DoesNotExist, ValueError):
         raise Http404
 
 
     camp = _get_camp_or_404(year, number)
     try:
         ref_id = int(request.GET.get('ref_id'))
-    except ValueError, TypeError:
+    except (ValueError, TypeError):
         raise Http404
     ref = get_object_or_404(Reference.objects.filter(id=ref_id))
     app = ref.application
     camp = _get_camp_or_404(year, number)
     try:
         ref_id = int(request.GET.get('ref_id'))
-    except ValueError, TypeError:
+    except (ValueError, TypeError):
         raise Http404
     ref = get_object_or_404(Reference.objects.filter(id=ref_id))
     app = ref.application
     camp = _get_camp_or_404(year, number)
     for officer_id in request.POST['officer_ids'].split(','):
         try:
-            i = Invitation.objects.get(camp=camp, officer=User.objects.get(id=int(officer_id)))
+            Invitation.objects.get(camp=camp, officer=User.objects.get(id=int(officer_id)))
         except Invitation.DoesNotExist:
-            i = Invitation.objects.create(camp=camp,
-                                          officer=User.objects.get(id=int(officer_id)),
-                                          date_added=datetime.date.today())
+            Invitation.objects.create(camp=camp,
+                                      officer=User.objects.get(id=int(officer_id)),
+                                      date_added=datetime.date.today())
     return {'status':'success'}
 
 
 @json_response
 def undo_mark_crb_sent(request):
     crbformlog_id = int(request.POST['crbformlog_id'])
-    c = CRBFormLog.objects.filter(id=crbformlog_id).delete()
+    CRBFormLog.objects.filter(id=crbformlog_id).delete()
     return {'status':'success'}
 
 
 def crb_consent_problem(request):
     try:
         app_id = int(request.GET.get('application_id'))
-    except ValueError, TypeError:
+    except (ValueError, TypeError):
         raise Http404
     app = get_object_or_404(Application.objects.filter(id=app_id))
     officer = app.officer

File cciw/settings.py

 LIVEBOX = not DEVBOX
 
 if LIVEBOX:
-    from cciw.settings_priv import PRODUCTION, STAGING
+    from cciw.settings_priv import PRODUCTION, STAGING, GOOGLE_ANALYTICS_ACCOUNT
 
 WEBSERVER_RUNNING = 'mod_wsgi' in sys.argv
 

File cciw/sitecontent/views.py

 from django.shortcuts import render
 from django.http import Http404
 
-from cciw.cciwmain.common import *
 from cciw.sitecontent.models import MenuLink
 
 def find(request):
     run("ln -s %s %s" % (version.src_dir, target.current_version.src_dir))
 
 
-def _fix_ipython():
-    # Fix up IPython, which gets borked by the re-installation of the virtualenv
-    with settings(warn_only=True):
-        run_venv("pip uninstall -y ipython")
-        run_venv("pip install ipython")
-
-
 def _update_virtualenv(version):
     # Update virtualenv in new dir.
     with cd(version.src_dir):
         with virtualenv(version.venv_dir):
             with cd(version.project_dir):
                 run_venv("pip install -r requirements.txt")
-            _fix_ipython()
 
         # Need to add project and deps to path.
         # Could do 'python setup.py develop' but not all projects support it
 #!/usr/bin/env python2.5
 import warnings
 #warnings.simplefilter("error", PendingDeprecationWarning)
+import os
+os.environ['DJANGO_SETTINGS_MODULE'] = 'cciw.settings'
 from django.core import management
 if __name__ == "__main__":
     management.execute_from_command_line()

File requirements.txt

 psycopg2==2.2.2
 twill==0.9
 zc.lockfile==1.0.0
-ipython
 south==0.7.2

File templates/admin/base_site.html

    $(document).ready(cciw.externalLinks);
 })(jQuery);
 </script>
+{% if GOOGLE_ANALYTICS_ACCOUNT %}
 <script type="text/javascript">
 
   var _gaq = _gaq || [];
-  _gaq.push(['_setAccount', 'UA-23715914-1']);
+  _gaq.push(['_setAccount', '{{ GOOGLE_ANALYTICS_ACCOUNT }}']);
   _gaq.push(['_trackPageview']);
 
   (function() {
   })();
 
 </script>
+{% endif %}
 {% endblock %}
 {% block branding %}
 <div id="header2">

File templates/cciw/base.html

 <link href="https://fonts.googleapis.com/css?family=Amaranth" rel="stylesheet" type="text/css" />
 <link rel="stylesheet" href="{{ STATIC_URL }}css/style.css" type="text/css" />
 {% block extraheader %}{% endblock %}
+{% if GOOGLE_ANALYTICS_ACCOUNT %}
 <script type="text/javascript">
 
   var _gaq = _gaq || [];
-  _gaq.push(['_setAccount', 'UA-23715914-1']);
+  _gaq.push(['_setAccount', '{{ GOOGLE_ANALYTICS_ACCOUNT }}']);
   _gaq.push(['_trackPageview']);
 
   (function() {
   })();
 
 </script>
+{% endif %}
 </head>
 <body>
 {% block bodystart %}