Merge soc/logic/out_of_band.py into soc/views/out_of_band.py. Merge
authorTodd Larsen <tlarsen@google.com>
Sat, 22 Nov 2008 07:57:00 +0000
changeset 543 280a1ac6bcc1
parent 542 7cc99461b64d
child 544 10f9da7e0d17
Merge soc/logic/out_of_band.py into soc/views/out_of_band.py. Merge errorResponse() and requestLogin() from soc/views/simple.py into out_of_band.Error and out_of_band.LoginRequest exception classes, respectively. Remove no-longer-used soc/logic/out_of_band.py and soc/views/simple.py. Fix some problems where usage of out_of_band was broken. Patch by: Todd Larsen
app/soc/logic/accounts.py
app/soc/logic/models/base.py
app/soc/logic/out_of_band.py
app/soc/templates/soc/error.html
app/soc/templates/soc/login.html
app/soc/views/helper/access.py
app/soc/views/models/base.py
app/soc/views/models/role.py
app/soc/views/models/user.py
app/soc/views/out_of_band.py
app/soc/views/simple.py
--- a/app/soc/logic/accounts.py	Sat Nov 22 03:13:59 2008 +0000
+++ b/app/soc/logic/accounts.py	Sat Nov 22 07:57:00 2008 +0000
@@ -26,7 +26,7 @@
 from google.appengine.api import users
 
 from soc.logic import models
-from soc.logic import out_of_band
+from soc.views import out_of_band
 
 import soc.models.user
 import soc.logic.models.user
@@ -117,7 +117,7 @@
   """Like getUserFromLinkId but expects to find a user.
 
   Raises:
-    out_of_band.ErrorResponse if no User entity is found
+    out_of_band.Error if no User entity is found
   """
   user = models.user.logic.getForFields({'link_id': link_id},
                                         unique=True)
@@ -125,5 +125,5 @@
   if user:
     return user
 
-  raise out_of_band.ErrorResponse(
+  raise out_of_band.Error(
       'There is no user with a "link ID" of "%s".' % link_id, status=404)
--- a/app/soc/logic/models/base.py	Sat Nov 22 03:13:59 2008 +0000
+++ b/app/soc/logic/models/base.py	Sat Nov 22 07:57:00 2008 +0000
@@ -30,7 +30,7 @@
 from django.utils.translation import ugettext_lazy
 
 from soc.logic import dicts
-from soc.logic import out_of_band
+from soc.views import out_of_band
 
 
 class Error(Exception):
@@ -218,7 +218,7 @@
       * Entity for supplied fields
 
     Raises:
-      out_of_band.ErrorResponse if link ID is not false, but no entity
+      out_of_band.Error if link ID is not false, but no entity
       with the supplied link ID exists in the Datastore.
     """
 
@@ -245,7 +245,7 @@
 
 
     # else: fields were supplied, but there is no Entity that has it
-    raise out_of_band.ErrorResponse(msg, status=404)
+    raise out_of_band.Error(msg, status=404)
 
   def getKeyNameForFields(self, fields):
     """Return a Datastore key_name for a Entity from the specified fields.
--- a/app/soc/logic/out_of_band.py	Sat Nov 22 03:13:59 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-#!/usr/bin/python2.5
-#
-# Copyright 2008 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Out-of-band responses to render instead of the usual HTTP response.
-"""
-
-__authors__ = [
-  '"Todd Larsen" <tlarsen@google.com>',
-  ]
-
-
-class OutOfBandResponse(Exception):
-  """Base exception for out-of-band responses raised by controller logic.
-  """
-
-  pass
-
-
-class ErrorResponse(OutOfBandResponse):
-  """Out-of-band response when controller logic needs a special error page.
-  """
-
-  def __init__(self, message, **response_args):
-    """Constructor used to set error message and HTTP response arguments.
-  
-    Args:
-      message: error message to display on the error page
-      **response_args: keyword arguments that are supplied directly to
-        django.http.HttpResponse; the most commonly used is 'status' to
-        set the HTTP status code for the response
-    """
-
-    self.message = message
-    self.response_args = response_args
--- a/app/soc/templates/soc/error.html	Sat Nov 22 03:13:59 2008 +0000
+++ b/app/soc/templates/soc/error.html	Sat Nov 22 07:57:00 2008 +0000
@@ -12,8 +12,29 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 {% endcomment %}
-{% block page_title %}Error{%if error_status %} {{ error_status }}{% endif %}{% endblock %}
-{% block header_title %}Error{%if error_status %} {{ error_status }}{% endif %}{% endblock %}
+{% block page_title %}
+ {%if title %}
+  {{ title }}
+ {% else %}
+  Error{% if status %} {{ status }}{% endif %}
+ {% endif %}
+{% endblock %}
+{% block header_title %}
+ {%if header %}
+  {{ header }}
+ {% else %}
+  {% comment %}
+   Attempt to use title again if header is not defined.
+  {% endcomment %}
+  {%if title %}
+   {{ title }}
+  {% else %}
+   Error{% if status %} {{ status }}{% endif %}
+  {% endif %}
+ {% endif %}
+{% endblock %}
 {% block body %}
-<div class="error">{%if error_status %}Error {{ error_status }}: {% endif %}{{ error_message|safe }}</div>
-{% endblock %}
\ No newline at end of file
+<div class="error">
+{%if status %}Error {{ status }}: {% endif %}{{ message|safe }}
+</div>
+{% endblock %}
--- a/app/soc/templates/soc/login.html	Sat Nov 22 03:13:59 2008 +0000
+++ b/app/soc/templates/soc/login.html	Sat Nov 22 07:57:00 2008 +0000
@@ -13,26 +13,26 @@
 limitations under the License.
 {% endcomment %}
 {% block page_title %}
- {%if login_title %}
-  {{ login_title }}
+ {%if title %}
+  {{ title }}
  {% else %}
   Sign In Required
  {% endif %}
 {% endblock %}
 {% block header_title %}
- {%if login_header %}
-  {{ login_header }}
+ {%if header %}
+  {{ header }}
  {% else %}
   {% comment %}
-   Attempt to use login_title again if login_header is not defined.
+   Attempt to use title again if header is not defined.
   {% endcomment %}
-  {%if login_title %}
-   {{ login_title }}
+  {%if title %}
+   {{ title }}
   {% else %}
    Sign In Required
   {% endif %}
  {% endif %}
 {% endblock %}
 {% block body %}
-<p>{{ login_message|safe }}</p>
-{% endblock %}
\ No newline at end of file
+<p>{{ message|safe }}</p>
+{% endblock %}
--- a/app/soc/views/helper/access.py	Sat Nov 22 03:13:59 2008 +0000
+++ b/app/soc/views/helper/access.py	Sat Nov 22 07:57:00 2008 +0000
@@ -38,15 +38,8 @@
 from soc.logic.models import user as user_logic
 from soc.logic.models import request as request_logic
 from soc.views import helper
-from soc.views.simple import requestLogin
-
-import soc.views.out_of_band
-
+from soc.views import out_of_band
 
-DEF_LOGIN_TMPL = 'soc/login.html'
-
-DEF_LOGIN_MSG_FMT = ugettext_lazy(
-  'Please <a href="%(sign_in)s">sign in</a> to continue.')
 
 DEF_NO_USER_LOGIN_MSG_FMT = ugettext_lazy(
   'Please create <a href="/user/edit">User Profile</a>'
@@ -65,7 +58,7 @@
   """Never returns an alternate HTTP response
 
   Args:
-    request: a django HTTP request
+    request: a Django HTTP request
   """
 
   return
@@ -74,26 +67,23 @@
   """Returns an alternate HTTP response
 
   Args:
-    request: a django HTTP request
+    request: a Django HTTP request
 
   Returns: a subclass of django.http.HttpResponse which contains the
   alternate response that should be returned by the calling view.
   """
 
   context = helper.responses.getUniversalContext(request)
-  context['login_title'] = 'Access denied'
-  context['login_header'] = 'Access denied'
-  context['login_message'] = DEF_PAGE_DENIED_MSG
+  context['title'] = 'Access denied'
 
-  denied_response = helper.responses.respond(request, DEF_LOGIN_TMPL, context=context)
+  raise out_of_band.AccessViolation(DEF_PAGE_DENIED_MSG, context=context)
 
-  raise soc.views.out_of_band.AccessViolationResponse(denied_response)
 
 def checkIsLoggedIn(request):
   """Returns an alternate HTTP response if Google Account is not logged in.
 
   Args:
-    request: A Django HTTP request
+    request: a Django HTTP request
 
    Raises:
      AccessViolationResponse: If the required authorization is not met.
@@ -107,17 +97,14 @@
   if users.get_current_user():
     return
 
-  login_response = requestLogin(request, None, DEF_LOGIN_TMPL,
-                                login_message_fmt=DEF_LOGIN_MSG_FMT)
-
-  raise soc.views.out_of_band.AccessViolationResponse(login_response)
+  raise out_of_band.LoginRequest()
 
 
 def checkIsUser(request):
   """Returns an alternate HTTP response if Google Account has no User entity.
 
   Args:
-    request: A Django HTTP request
+    request: a Django HTTP request
 
    Raises:
      AccessViolationResponse: If the required authorization is not met.
@@ -136,10 +123,7 @@
   if user:
     return
 
-  login_response = requestLogin(request, None, DEF_LOGIN_TMPL,
-                                login_message_fmt=DEF_NO_USER_LOGIN_MSG_FMT)
-
-  raise soc.views.out_of_band.AccessViolationResponse(login_response)
+  raise out_of_band.LoginRequest(message_fmt=DEF_NO_USER_LOGIN_MSG_FMT)
 
 
 def checkIsDeveloper(request):
@@ -163,13 +147,9 @@
     return None
 
   login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % {
-      'role' : 'a site developer ',
-      }
+      'role': 'a site developer '}
 
-  login_response = requestLogin(request, None, DEF_LOGIN_TMPL,
-                                login_message_fmt=login_message_fmt)
-
-  raise soc.views.out_of_band.AccessViolationResponse(login_response)
+  raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
 
 
 def checkIsInvited(request, role):
@@ -205,10 +185,6 @@
     return
 
   login_message_fmt = DEF_DEV_LOGOUT_LOGIN_MSG_FMT % {
-      'role' : 'a host for this program',
-      }
+      'role': 'a host for this program'}
 
-  login_response = requestLogin(request, None, DEF_LOGIN_TMPL,
-                                login_message_fmt=login_message_fmt)
-
-  raise soc.views.out_of_band.AccessViolationResponse(login_response)
+  raise out_of_band.LoginRequest(message_fmt=login_message_fmt)
--- a/app/soc/views/models/base.py	Sat Nov 22 03:13:59 2008 +0000
+++ b/app/soc/views/models/base.py	Sat Nov 22 07:57:00 2008 +0000
@@ -30,16 +30,14 @@
 
 import soc.logic
 import soc.logic.lists
-import soc.logic.out_of_band
 import soc.views.helper.lists
 import soc.views.helper.responses
-import soc.views.out_of_band
 
 from soc.logic import dicts
 from soc.logic import models
 from soc.models import linkable
-from soc.views import simple
 from soc.views import helper
+from soc.views import out_of_band
 from soc.views.helper import access
 
 
@@ -153,8 +151,8 @@
 
     try:
       self.checkAccess('public', request)
-    except soc.views.out_of_band.AccessViolationResponse, alt_response:
-      return alt_response.response()
+    except out_of_band.Error, error:
+      return error.response(request)
 
     # create default template context for use with any templates
     context = helper.responses.getUniversalContext(request)
@@ -168,9 +166,9 @@
     try:
       key_fields = self._logic.getKeyFieldsFromDict(kwargs)
       entity = self._logic.getIfFields(key_fields)
-    except soc.logic.out_of_band.ErrorResponse, error:
-      template = params['public_template']
-      return simple.errorResponse(request, page_name, error, template, context)
+    except out_of_band.Error, error:
+      return error.response(request, template=params['public_template'],
+                            context=context)
 
     self._public(request, entity, context)
 
@@ -208,7 +206,8 @@
       return self.edit(request, page_name=page_name, params=params,
                        **empty_kwargs)
     else:
-      return self.edit(request, page_name=page_name, params=params, seed=kwargs, **empty_kwargs)
+      return self.edit(request, page_name=page_name, params=params,
+                       seed=kwargs, **empty_kwargs)
 
   def edit(self, request, page_name=None, params=None, seed=None, **kwargs):
     """Displays the edit page for the entity specified by **kwargs.
@@ -224,8 +223,8 @@
 
     try:
       self.checkAccess('edit', request, rights=params['rights'])
-    except soc.views.out_of_band.AccessViolationResponse, alt_response:
-      return alt_response.response()
+    except out_of_band.Error, error:
+      return error.response(request)
 
     context = helper.responses.getUniversalContext(request)
     context['page_name'] = page_name
@@ -235,16 +234,15 @@
       if all(kwargs.values()):
         key_fields = self._logic.getKeyFieldsFromDict(kwargs)
         entity = self._logic.getIfFields(key_fields)
-    except soc.logic.out_of_band.ErrorResponse, error:
+    except out_of_band.Error, error:
       if not seed:
-        template = params['public_template']
-        error.message = error.message + self.DEF_CREATE_NEW_ENTITY_MSG_FMT % {
+        error.message_fmt = (
+          error.message_fmt + self.DEF_CREATE_NEW_ENTITY_MSG_FMT % {
             'entity_type_lower' : params['name'].lower(),
             'entity_type' : params['name'],
-            'create' : params['missing_redirect']
-            }
-        return simple.errorResponse(request, page_name, error, template,
-                                    context)
+            'create' : params['missing_redirect']})
+        return error.response(request, template=params['public_template'],
+                              context=context)
 
     if request.method == 'POST':
       return self.editPost(request, entity, context, params)
@@ -338,8 +336,8 @@
 
     try:
       self.checkAccess('list', request)
-    except soc.views.out_of_band.AccessViolationResponse, alt_response:
-      return alt_response.response()
+    except out_of_band.Error, error:
+      return error.response(request)
 
     context = helper.responses.getUniversalContext(request)
     context['page_name'] = page_name
@@ -349,9 +347,9 @@
 
     # Fetch one more to see if there should be a 'next' link
     if not filter:
-      entities = self._logic.getForLimitAndOffset(limit + 1, offset=offset)
+      entities = self._logic.getForLimitAndOffset(limit+1, offset=offset)
     else:
-      entities = self._logic.getForFields(filter, limit=limit + 1, offset=offset)
+      entities = self._logic.getForFields(filter, limit=limit+1, offset=offset)
     
     context['pagination_form'] = helper.lists.makePaginationForm(request, limit)
 
@@ -387,8 +385,8 @@
 
     try:
       self.checkAccess('delete', request)
-    except soc.views.out_of_band.AccessViolationResponse, alt_response:
-      return alt_response.response()
+    except out_of_band.Error, error:
+      return error.response(request)
 
     # create default template context for use with any templates
     context = helper.responses.getUniversalContext(request)
@@ -398,14 +396,14 @@
     try:
       key_fields = self._logic.getKeyFieldsFromDict(kwargs)
       entity = self._logic.getIfFields(key_fields)
-    except soc.logic.out_of_band.ErrorResponse, error:
-      template = params['edit_template']
-      error.message = error.message + self.DEF_CREATE_NEW_ENTITY_MSG_FMT % {
+    except out_of_band.Error, error:
+      error.message_fmt = (
+        error.message_fmt + self.DEF_CREATE_NEW_ENTITY_MSG_FMT % {
           'entity_type_lower' : params['name'].lower(),
           'entity_type' : params['name'],
-          'create' : params['missing_redirect']
-          }
-      return simple.errorResponse(request, page_name, error, template, context)
+          'create' : params['missing_redirect']})
+      return error.response(request, template=params['edit_template'],
+                            context=context)
 
     if not entity:
       #TODO: Create a proper error page for this
--- a/app/soc/views/models/role.py	Sat Nov 22 03:13:59 2008 +0000
+++ b/app/soc/views/models/role.py	Sat Nov 22 07:57:00 2008 +0000
@@ -33,6 +33,7 @@
 from soc.logic.models import request as request_logic
 from soc.logic.models import user as user_logic
 from soc.views import helper
+from soc.views import out_of_band
 from soc.views.models import base
 from soc.views.models import user as user_view
 
@@ -103,8 +104,8 @@
 
     try:
       self.checkAccess('invite', request)
-    except soc.views.out_of_band.AccessViolationResponse, alt_response:
-      return alt_response.response()
+    except out_of_band.Error, error:
+      return error.response(request)
 
     return user_view.list(request, page_name=page_name, params=params)
 
--- a/app/soc/views/models/user.py	Sat Nov 22 03:13:59 2008 +0000
+++ b/app/soc/views/models/user.py	Sat Nov 22 07:57:00 2008 +0000
@@ -32,6 +32,7 @@
 from soc.logic import validate
 from soc.logic.models import user as user_logic
 from soc.views import helper
+from soc.views import out_of_band
 from soc.views.helper import access
 from soc.views.models import base
 
@@ -183,6 +184,8 @@
 
     base.View.__init__(self, params=params)
 
+  EDIT_SELF_TMPL = 'soc/user/edit_self.html'
+
   def editSelf(self, request, page_name=None, params=None, **kwargs):
     """Displays User self edit page for the entity specified by **kwargs.
 
@@ -200,11 +203,11 @@
 
     try:
       self.checkAccess('editSelf', request, rights=rights)
-    except soc.views.out_of_band.AccessViolationResponse, alt_response:
-      return alt_response.response()
+    except out_of_band.Error, error:
+      return error.response(request, template=self.EDIT_SELF_TMPL)
 
     new_params = {}
-    new_params['edit_template'] = 'soc/user/edit_self.html'
+    new_params['edit_template'] = self.EDIT_SELF_TMPL
     new_params['rights'] = rights
 
     params = dicts.merge(params, new_params)
@@ -232,10 +235,8 @@
         # check if user account is not in former_accounts
         # if it is show error message that account is invalid
         if soc.logic.models.user.logic.isFormerAccount(account):
-          msg = DEF_USER_ACCOUNT_INVALID_MSG
-          error = out_of_band.ErrorResponse(msg)
-          return simple.errorResponse(request, page_name, error, template,
-                                      context)
+          error = out_of_band.Error(DEF_USER_ACCOUNT_INVALID_MSG)
+          return error.response(request, template=template, context=context)
 
         user = soc.logic.models.user.logic.updateOrCreateFromFields(
             properties, {'link_id': new_link_id})
--- a/app/soc/views/out_of_band.py	Sat Nov 22 03:13:59 2008 +0000
+++ b/app/soc/views/out_of_band.py	Sat Nov 22 07:57:00 2008 +0000
@@ -18,32 +18,100 @@
 """
 
 __authors__ = [
+  '"Todd Larsen" <tlarsen@google.com>',
   '"Sverre Rabbelier" <sverre@rabbelier.nl>',
   ]
 
 
-class OutOfBandResponse(Exception):
-  """Base exception for out-of-band responses raised by views.
-  """
+from django.utils.translation import ugettext_lazy
 
-  pass
+from soc.views import helper
+
+import soc.views.helper.responses
+import soc.views.helper.templates
 
 
-class AccessViolationResponse(OutOfBandResponse):
-  """"Out of band response when an access requirement was not met.
+class Error(Exception):
+  """Base exception for out-of-band responses raised by logic or views.
   """
+  TEMPLATE_NAME = 'error.html'
+  DEF_TEMPLATE = 'soc/error.html'
 
-  def __init__(self, response):
-    """Constructor used to set response message.
+  def __init__(self, message_fmt, context=None, **response_args):
+    """Constructor used to set response message and HTTP response arguments.
+  
+    Args:
+      message_fmt: format string, when combined with a context supplied to
+        the response() method, produces the message to display on the
+        response page; this can be a simple string containing *no* named
+        format specifiers
+      context: see response()
+      **response_args: keyword arguments that are supplied directly to
+        django.http.HttpResponse; the most commonly used is 'status' to
+        set the HTTP status code for the response
+    """
+    self.message_fmt = message_fmt
+    self._context = context
+    self._response_args = response_args
 
+  def response(self, request, template=None, context=None):
+    """Creates an HTTP response from the OutOfBandResponse exception.
+  
     Args:
-      response: The response that should be returned to the user.
+      request: a Django HTTP request
+      template: the "sibling" template (or a search list of such templates)
+        from which to construct the actual template name (or names)
+      context: optional context dict supplied to the template, which is
+        modified (so supply a copy if such modification is not acceptable)
     """
+    if not context:
+      context = self._context
 
-    self._response = response
+    if not context:
+      context = helper.responses.getUniversalContext(request)
+
+    if not template:
+      template = []
+
+    # make a list of possible "sibling" templates, then append a default
+    templates = helper.templates.makeSiblingTemplatesList(template,
+        self.TEMPLATE_NAME, default_template=self.DEF_TEMPLATE)
+
+    context['status'] = self._response_args.get('status')
+
+    if not context.get('message'):
+      # supplied context did not explicitly override the message
+      context['message'] = self.message_fmt % context
+
+    return helper.responses.respond(request, templates, context=context,
+                                    response_args=self._response_args)
+
 
-  def response(self):
-    """Returns the response that was set in the constructor.
+class LoginRequest(Error):
+  """Out of band error raised when login is requested.
+  """
+  TEMPLATE_NAME = 'login.html'
+  DEF_TEMPLATE = 'soc/login.html'
+
+  DEF_LOGIN_MSG_FMT = ugettext_lazy(
+      'Please <a href="%(sign_in)s">sign in</a> to continue.')
+
+  def __init__(self, message_fmt=None, **response_args):
+    """Constructor used to set response message and HTTP response arguments.
+  
+    Args:
+      message_fmt: same as Error.__init__() message_fmt, with the addition
+        of a default value of None, in which case self.DEF_LOGIN_MSG_FMT is
+        used
+      **response_args: see Error.__init__()
     """
+    if not message_fmt:
+      message_fmt = self.DEF_LOGIN_MSG_FMT
 
-    return self._response
+    Error.__init__(self, message_fmt, **response_args)
+
+
+class AccessViolation(Error):
+  """"Out of band error raised when an access requirement was not met.
+  """
+  pass
--- a/app/soc/views/simple.py	Sat Nov 22 03:13:59 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-#!/usr/bin/python2.5
-#
-# Copyright 2008 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Simple views that depend entirely on the template and context.
-"""
-
-__authors__ = [
-  '"Todd Larsen" <tlarsen@google.com>',
-  '"Pawel Solyga" <pawel.solyga@gmail.com>',
-  ]
-
-
-from django.utils.translation import ugettext_lazy
-
-from soc.logic import accounts
-from soc.logic import out_of_band
-from soc.views import helper
-from soc.views.helper import decorators
-
-import soc.views.helper.responses
-import soc.views.helper.templates
-
-
-DEF_PUBLIC_TMPL = 'soc/base.html'
-
-@decorators.view
-def public(request, page_name=None, template=DEF_PUBLIC_TMPL, link_id=None,
-           context=None):
-  """A simple template view that expects a link_id extracted from the URL.
-
-  Args:
-    request: the standard Django HTTP request object
-    page_name: the page name displayed in templates as page and header title
-    template: the template to use for rendering the view (or a search list
-      of templates)
-    link_id: a site-unique "link_id" (usually extracted from the URL)
-    context: the context dict supplied to the template, which is modified
-      (so supply a copy if such modification is not acceptable)
-    link_id: the link_id parameter is added to the context
-    link_id_user: if the link_id exists for a User, that User
-      is added to the context
-
-
-  Returns:
-    A subclass of django.http.HttpResponse containing the generated page.
-  """
-
-  template = helper.templates.makeSiblingTemplatesList(template, 'public.html')
-
-  # TODO(tlarsen): fix getUniversalContext() so that it is back to being a
-  #   dict merge of missing defaults (as discussed at length in recent code
-  #   reviews)
-  if not context:
-    context = helper.responses.getUniversalContext(request)
-
-  context['page_name'] = page_name
-
-  try:
-    if link_id:
-      user = accounts.getUserFromLinkIdOr404(link_id)
-  except out_of_band.ErrorResponse, error:
-    return errorResponse(request, page_name, error, template, context)
-
-  context['link_id'] = link_id
-  context['link_id_user'] = user
-
-  return helper.responses.respond(request, template, context)
-
-
-DEF_ERROR_TMPL = 'soc/error.html'
-
-def errorResponse(request, page_name, error, template, context):
-  """Displays an error page for an out_of_band.ErrorResponse exception.
-  
-  Args:
-    request: the standard Django HTTP request object
-    page_name: the page name displayed in templates as page and header title
-    error: an out_of_band.ErrorResponse exception
-    template: the "sibling" template (or a search list of such templates)
-      from which to construct the error.html template name (or names)
-    context: the context dict supplied to the template, which is modified
-      (so supply a copy if such modification is not acceptable)
-    error_message: the error message string from error.message
-    error_status: error.response_args['status'], or None if a status code
-      was not supplied to the ErrorResponse
-
-  """
-
-  if not context:
-    context = helper.responses.getUniversalContext(request)
-
-  # make a list of possible "sibling" templates, then append a default
-  error_templates = helper.templates.makeSiblingTemplatesList(
-      template, 'error.html', default_template=DEF_ERROR_TMPL)
-
-  context['error_status'] = error.response_args.get('status')
-  context['error_message'] = error.message
-
-  return helper.responses.respond(request, error_templates, context=context,
-                                  response_args=error.response_args)
-
-
-DEF_LOGIN_TMPL = 'soc/login.html'
-DEF_LOGIN_MSG_FMT = ugettext_lazy(
-  'Please <a href="%(sign_in)s">sign in</a> to continue.')
-
-def requestLogin(request, page_name, template, context=None, login_message_fmt=None):
-  """Displays a login request page with custom message and login link.
-  
-  Args:
-    request: the standard Django HTTP request object
-    page_name: the page name displayed in templates as page and header title
-    template: the "sibling" template (or a search list of such templates)
-      from which to construct the login.html template name (or names)
-    login_message_fmt: a custom message format string used to create a
-      message displayed on the login page; the format string can contain
-      named format specifiers for any of the keys in context, but should at
-      least contain %(sign_in)s
-    context: the context dict supplied to the template, which is modified
-      (so supply a copy if such modification is not acceptable)
-    login_message: the caller can completely construct the message supplied
-      to the login template in lieu of using login_message_fmt
-
-  """
-
-  if not context:
-    context = helper.responses.getUniversalContext(request)
-  
-  # make a list of possible "sibling" templates, then append a default
-  login_templates = helper.templates.makeSiblingTemplatesList(
-      template, 'login.html', default_template=DEF_LOGIN_TMPL)
-  
-  if not context.get('login_message'):
-    if not login_message_fmt:
-      login_message_fmt = DEF_LOGIN_MSG_FMT
-    context['login_message'] = login_message_fmt % context  
-  
-  return helper.responses.respond(request, login_templates, context=context)
-