Commits

Luke Plant committed 53da3ac

Fixed dozens of instances where unicode should have been used instead of str

A definite bug in make_state_token fixed

Comments (0)

Files changed (5)

cciw/bookings/email.py

         }
 
     body = loader.render_to_string("cciw/bookings/verification_email.txt", c)
-    subject = "CCIW booking account"
+    subject = u"CCIW booking account"
     mail.send_mail(subject, body, settings.SERVER_EMAIL, [booking_account.email])
 
 
         }
 
     body = loader.render_to_string("cciw/bookings/unrecognised_payment_email.txt", c)
-    subject = "CCIW booking - unrecognised payment"
+    subject = u"CCIW booking - unrecognised payment"
     mail.send_mail(subject, body, settings.SERVER_EMAIL, [settings.WEBMASTER_EMAIL])
 
 
         'payment_received': 'payment_received' in kwargs,
         }
     body = loader.render_to_string('cciw/bookings/place_confirmed_email.txt', c)
-    subject = "CCIW booking - place confirmed"
+    subject = u"CCIW booking - place confirmed"
     mail.send_mail(subject, body, settings.SERVER_EMAIL, [account.email])
 
 
         }
     body = loader.render_to_string('cciw/bookings/place_expired_mail.txt', c)
     if expired:
-        subject = "CCIW booking - booking expired"
+        subject = u"CCIW booking - booking expired"
     else:
-        subject = "CCIW booking - booking expiry warning"
+        subject = u"CCIW booking - booking expiry warning"
     mail.send_mail(subject, body, settings.SERVER_EMAIL, [account.email])

cciw/bookings/models.py

         if self.post_code:
             out.append(self.post_code)
         if self.email:
-            out.append("<" + self.email + ">")
+            out.append(u"<" + self.email + u">")
         if not out:
-            out.append("(empty)")
+            out.append(u"(empty)")
         return u", ".join(out)
 
     # Business methods:
     # Methods
 
     def __unicode__(self):
-        return "%s, %s-%s, %s" % (self.name, self.camp.year, self.camp.number,
+        return u"%s, %s-%s, %s" % (self.name, self.camp.year, self.camp.number,
                                   self.account)
 
     ### Main business rules here ###
 
         # Custom price - not auto bookable
         if self.price_type == PRICE_CUSTOM:
-            errors.append("A custom discount needs to be arranged by the booking secretary")
+            errors.append(u"A custom discount needs to be arranged by the booking secretary")
 
         # 2nd/3rd child discounts
         if self.price_type == PRICE_2ND_CHILD:
             qs = self.account.bookings.filter(shelved=False, camp__year__exact=self.camp.year)
             if not qs.filter(price_type=PRICE_FULL).exists():
-                errors.append("You cannot use a 2nd child discount unless you have "
-                              "a child at full price. Please edit the place details "
-                              "and choose an appropriate price type.")
+                errors.append(u"You cannot use a 2nd child discount unless you have "
+                              u"a child at full price. Please edit the place details "
+                              u"and choose an appropriate price type.")
 
         if self.price_type == PRICE_3RD_CHILD:
             qs = self.account.bookings.filter(shelved=False, camp__year__exact=self.camp.year)
             qs = qs.filter(price_type=PRICE_FULL) | qs.filter(price_type=PRICE_2ND_CHILD)
             if qs.count() < 2:
-                errors.append("You cannot use a 3rd child discount unless you have "
-                              "two other places without this discount. Please edit the "
-                              "place details and choose an appropriate price type.")
+                errors.append(u"You cannot use a 3rd child discount unless you have "
+                              u"two other places without this discount. Please edit the "
+                              u"place details and choose an appropriate price type.")
 
         # serious illness
         if self.serious_illness:
-            errors.append("Must be approved by leader due to serious illness/condition")
+            errors.append(u"Must be approved by leader due to serious illness/condition")
 
         # Check age.
         # Age is calculated based on shool years, i.e. age on 31st August
         camper_age = relativedelta(date(self.camp.year, 8, 31), self.date_of_birth)
         if camper_age.years < self.camp.minimum_age:
-            errors.append("Camper will be below the minimum age (%d) on the 31st August %d"
+            errors.append(u"Camper will be below the minimum age (%d) on the 31st August %d"
                           % (self.camp.minimum_age, self.camp.year))
 
         if camper_age.years > self.camp.maximum_age:
-            errors.append("Camper will be above the maximum age (%d) on the 31st August %d"
+            errors.append(u"Camper will be above the maximum age (%d) on the 31st August %d"
                           % (self.camp.maximum_age, self.camp.year))
 
         # Check place availability
 
         # Simple - no places left
         if places_left <= 0:
-            errors.append("There are no places left on this camp.")
+            errors.append(u"There are no places left on this camp.")
             places_available = False
 
         if places_available and self.sex == SEX_MALE:
             if places_left_male <= 0:
-                errors.append("There are no places left for boys on this camp.")
+                errors.append(u"There are no places left for boys on this camp.")
                 places_available = False
 
         if places_available and self.sex == SEX_FEMALE:
             if places_left_female <= 0:
-                errors.append("There are no places left for girls on this camp.")
+                errors.append(u"There are no places left for girls on this camp.")
                 places_available = False
 
         if places_available:
             places_to_be_booked_female = same_camp_bookings.filter(sex=SEX_FEMALE).count()
 
             if places_left < places_to_be_booked:
-                errors.append("There are not enough places left on this camp "
-                              "for the campers in this set of bookings.")
+                errors.append(u"There are not enough places left on this camp "
+                              u"for the campers in this set of bookings.")
                 places_available = False
 
             if places_available and self.sex == SEX_MALE:
                 if places_left_male < places_to_be_booked_male:
-                    errors.append("There are not enough places for boys left on this camp "
-                                  "for the campers in this set of bookings.")
+                    errors.append(u"There are not enough places for boys left on this camp "
+                                  u"for the campers in this set of bookings.")
                     places_available = False
 
             if places_available and self.sex == SEX_FEMALE:
                 if places_left_female < places_to_be_booked_female:
-                    errors.append("There are not enough places for girls left on this camp "
-                                  "for the campers in this set of bookings.")
+                    errors.append(u"There are not enough places for girls left on this camp "
+                                  u"for the campers in this set of bookings.")
                     places_available = False
 
         if self.account.bookings.filter(name=self.name).exclude(id=self.id):

cciw/bookings/templatetags/bookings.py

     has_account_details = logged_in and request.booking_account.has_account_details()
 
     # Tuple of (name, caption, if this a link, url, message if inaccessible):
-    msg_need_login = 'Must be logged in to access this'
-    msg_need_account_details = 'Need account details to access this' if logged_in else 'Must be logged in to access this'
+    msg_need_login = u'Must be logged in to access this'
+    msg_need_account_details = u'Need account details to access this' if logged_in else 'Must be logged in to access this'
     stages = [
-        ('email',  'Log in', False,
+        ('email',  u'Log in', False,
          '',
-         'Use the "log out" link if you need to log in as someone else'),
+         u'Use the "log out" link if you need to log in as someone else'),
 
-        ('account', 'Account details', logged_in,
+        ('account', u'Account details', logged_in,
          reverse('cciw.bookings.views.account_details'),
          msg_need_login),
 
-        ('place', 'Place details', logged_in and has_account_details,
+        ('place', u'Place details', logged_in and has_account_details,
          reverse('cciw.bookings.views.add_place'),
          msg_need_account_details),
 
-        ('list', 'Checkout', logged_in and has_account_details,
+        ('list', u'Checkout', logged_in and has_account_details,
          reverse('cciw.bookings.views.list_bookings'),
          msg_need_account_details),
 
-        ('pay', 'Pay', logged_in and has_account_details,
+        ('pay', u'Pay', logged_in and has_account_details,
          reverse('cciw.bookings.views.pay'),
          msg_need_account_details),
 
         ]
 
     out = []
-    out.append("""
+    out.append(u"""
 <div id="bookingbar">
   <div id="bookingbartop">""")
 
     if not logged_in:
-        out.append("Not logged in")
+        out.append(u"Not logged in")
     else:
-        out.append("Booking account: %s" % escape(request.booking_account.email))
-        out.append(' | <a href="%s">Account overview</a>' % escape(reverse('cciw.bookings.views.account_overview')))
-        out.append(' | <a href="%s">Log out</a>' % escape(reverse('cciw.bookings.views.logout')))
-    out.append("</div>")
+        out.append(u"Booking account: %s" % escape(request.booking_account.email))
+        out.append(u' | <a href="%s">Account overview</a>' % escape(reverse('cciw.bookings.views.account_overview')))
+        out.append(u' | <a href="%s">Log out</a>' % escape(reverse('cciw.bookings.views.logout')))
+    out.append(u"</div>")
 
-    out.append("<ul>")
+    out.append(u"<ul>")
     for name, caption, is_link, url, msg in stages:
         if is_link and name != current_stage:
-            out.append('<li><a href="%s">%s</a></li>' % (escape(url), escape(caption)))
+            out.append(u'<li><a href="%s">%s</a></li>' % (escape(url), escape(caption)))
         elif name == current_stage:
-            out.append('<li><span class="active">%s</span></li>' % escape(caption))
+            out.append(u'<li><span class="active">%s</span></li>' % escape(caption))
         else:
-            out.append('<li><span title="%s">%s</span></li>' % (escape(msg), escape(caption)))
+            out.append(u'<li><span title="%s">%s</span></li>' % (escape(msg), escape(caption)))
 
-    out.append("</ul></div>")
-    return ''.join(out)
+    out.append(u"</ul></div>")
+    return u''.join(out)

cciw/bookings/tests.py

     def place_details(self):
         return {
             'camp': self.camp.id,
-            'name': 'Joe Bloggs',
+            'name': u'Frédéric Bloggs',
             'sex': 'm',
             'date_of_birth': '%d-01-01' % (get_thisyear() - 14),
             'address': 'x',
         self.assertEqual(200, resp.status_code)
 
         self.assertContains(resp, "Camp 1")
-        self.assertContains(resp, "Joe Bloggs")
+        self.assertContains(resp, "Frédéric Bloggs")
         self.assertContains(resp, "£100")
         self.assertContains(resp, "This place can be booked")
         self.assertContains(resp, ENABLED_BOOK_NOW_BUTTON)
         self.assertEqual(200, resp.status_code)
 
         self.assertContains(resp, "Camp 1")
-        self.assertContains(resp, "Joe Bloggs")
+        self.assertContains(resp, "Frédéric Bloggs")
         self.assertContains(resp, "TBA")
         self.assertContains(resp, "A custom discount needs to be arranged by the booking secretary")
         self.assertContains(resp, DISABLED_BOOK_NOW_BTN)
         self.assertEqual(200, resp.status_code)
 
         self.assertContains(resp, "Camp 1")
-        self.assertContains(resp, "Joe Bloggs")
+        self.assertContains(resp, "Frédéric Bloggs")
         self.assertContains(resp, "TBA")
         self.assertContains(resp, "A custom discount needs to be arranged by the booking secretary")
         self.assertContains(resp, DISABLED_BOOK_NOW_BTN)
         self.assertEqual(200, resp.status_code)
 
         self.assertContains(resp, "Camp 1")
-        self.assertContains(resp, "Joe Bloggs")
+        self.assertContains(resp, "Frédéric Bloggs")
         self.assertContains(resp, "£100")
         self.assertContains(resp, "This place can be booked")
 

cciw/bookings/views.py

 # Views
 
 class BookingIndex(DefaultMetaData, TemplateView):
-    metadata_title = "Booking"
+    metadata_title = u"Booking"
     template_name = "cciw/bookings/index.html"
 
     def get(self, request):
 
 
 class BookingStart(DefaultMetaData, FormMixin, TemplateResponseMixin, ProcessFormView):
-    metadata_title = "Booking - email address"
+    metadata_title = u"Booking - email address"
     form_class = EmailForm
     template_name = 'cciw/bookings/start.html'
     success_url = reverse_lazy('cciw.bookings.views.email_sent')
 
 
 class BookingEmailSent(DefaultMetaData, TemplateView):
-    metadata_title = "Booking - email address"
+    metadata_title = u"Booking - email address"
     template_name = "cciw/bookings/email_sent.html"
     extra_context = {'stage': 'email'}
 
 
 
 class BookingVerifyEmailFailed(DefaultMetaData, TemplateView):
-    metadata_title = "Booking - account email verification failed"
+    metadata_title = u"Booking - account email verification failed"
     template_name = "cciw/bookings/email_verification_failed.html"
     extra_context = {'stage': 'email'}
 
 
 class BookingNotLoggedIn(DefaultMetaData, TemplateView):
-    metadata_title = "Booking - not logged in"
+    metadata_title = u"Booking - not logged in"
     template_name = "cciw/bookings/not_logged_in.html"
 
 
 class BookingAccountDetails(DefaultMetaData, AjaxyFormMixin, TemplateResponseMixin, BaseUpdateView):
     __metaclass__ = AjaxMroFixer
-    metadata_title = "Booking - account details"
+    metadata_title = u"Booking - account details"
     form_class = AccountDetailsForm
     template_name = 'cciw/bookings/account_details.html'
     success_url = reverse_lazy('cciw.bookings.views.add_place')
         return self.request.booking_account
 
     def form_valid(self, form):
-        messages.info(self.request, 'Account details updated, thank you.')
+        messages.info(self.request, u'Account details updated, thank you.')
         return super(BookingAccountDetails, self).form_valid(form)
 
 
         form.instance.agreement_date = datetime.now()
         form.instance.auto_set_amount_due()
         form.instance.state = BOOKING_INFO_COMPLETE
-        messages.info(self.request, 'Details for "%s" were saved successfully' % form.instance.name)
+        messages.info(self.request, u'Details for "%s" were saved successfully' % form.instance.name)
         return super(BookingEditAddBase, self).form_valid(form)
 
 
 class BookingAddPlace(BookingEditAddBase, BaseCreateView):
     __metaclass__ = AjaxMroFixer
-    metadata_title = "Booking - add new place"
+    metadata_title = u"Booking - add new place"
     form_class = AddPlaceForm
 
 
 class BookingEditPlace(BookingEditAddBase, BaseUpdateView):
     __metaclass__ = AjaxMroFixer
-    metadata_title = "Booking - edit place"
+    metadata_title = u"Booking - edit place"
     form_class = AddPlaceForm
 
     def post(self, request, *args, **kwargs):
 def make_state_token(bookings):
     # Hash some key data about booking, without which the booking isn't valid.
     bookings.sort(key=lambda b: b.id)
-    data = '|'.join([':'.join(map(str, [b.id, b.camp.id, b.amount_due, b.name, b.price_type, b.state]))
+    data = u'|'.join([u':'.join(map(unicode, [b.id, b.camp.id, b.amount_due, b.name, b.price_type, b.state]))
                      for b in bookings])
-    return salted_hmac('cciw.bookings.state_token', data).hexdigest()
+    return salted_hmac('cciw.bookings.state_token', data.encode('utf-8')).hexdigest()
 
 
 class BookingListBookings(DefaultMetaData, TemplateView):
         def shelve(place):
             place.shelved = True
             place.save()
-            messages.info(self.request, 'Place for "%s" moved to shelf' % place.name)
+            messages.info(self.request, u'Place for "%s" moved to shelf' % place.name)
 
         def unshelve(place):
             place.shelved = False
             place.save()
-            messages.info(self.request, 'Place for "%s" moved to basket' % place.name)
+            messages.info(self.request, u'Place for "%s" moved to basket' % place.name)
 
         def delete(place):
-            messages.info(self.request, 'Place for "%s" deleted' % place.name)
+            messages.info(self.request, u'Place for "%s" deleted' % place.name)
             place.delete()
 
         def edit(place):
         if 'book_now' in request.POST:
             state_token = request.POST.get('state_token', '')
             if make_state_token(basket_bookings) != state_token:
-                messages.error(request, "Places were not booked due to modifications made "
-                               "to the details. Please check the details and try again.")
+                messages.error(request, u"Places were not booked due to modifications made "
+                               u"to the details. Please check the details and try again.")
             else:
                 if book_basket_now(basket_bookings):
-                    messages.info(request, "Places booked!")
+                    messages.info(request, u"Places booked!")
                     return HttpResponseRedirect(reverse('cciw.bookings.views.pay'))
                 else:
-                    messages.error(request, "These places cannot be booked for the reasons "
-                                   "given below.")
+                    messages.error(request, u"These places cannot be booked for the reasons "
+                                   u"given below.")
 
         return self.get(request, *args, **kwargs)
 
         paypal_dict = {
             "business": settings.PAYPAL_RECEIVER_EMAIL,
             "amount": str(balance),
-            "item_name": "Camp place booking",
+            "item_name": u"Camp place booking",
             "invoice": "%s-%s-%s" % (acc.id, balance,
                                      datetime.now()), # We don't need this, but must be unique
             "notify_url":  "%s://%s%s" % (protocol, domain, reverse('paypal-ipn')),
 
 
 class BookingPayDone(DefaultMetaData, TemplateView):
-    metadata_title = "Booking - payment complete"
+    metadata_title = u"Booking - payment complete"
     template_name = "cciw/bookings/pay_done.html"
     extra_context = {'stage': 'pay'}
 
         return self.get(*args, **kwargs)
 
 class BookingPayCancelled(DefaultMetaData, TemplateView):
-    metadata_title = "Booking - payment cancelled"
+    metadata_title = u"Booking - payment cancelled"
     template_name = "cciw/bookings/pay_cancelled.html"
     extra_context = {'stage': 'pay'}
 
 
 
 class BookingAccountOverview(DefaultMetaData, TemplateView):
-    metadata_title = "Booking - account overview"
+    metadata_title = u"Booking - account overview"
     template_name = 'cciw/bookings/account_overview.html'
     extra_context = {'stage': ''}