From 7d79f4fe3757a08e676bd906a392dd4bdf20961d Mon Sep 17 00:00:00 2001
From: Calen Pennington <cale@edx.org>
Date: Tue, 27 Aug 2013 15:52:14 -0400
Subject: [PATCH] Move mitxmako initialization to a startup module, called by lms.startup and cms.startup for both management commands and when run via wsgi

[DEVPAIN-7]
---
 common/djangoapps/mitxmako/middleware.py                         | 25 -------------------------
 common/djangoapps/mitxmako/shortcuts.py                          |  8 ++++----
 common/djangoapps/mitxmako/startup.py                            | 33 +++++++++++++++++++++++++++++++++
 common/djangoapps/mitxmako/template.py                           |  9 +++++----
 common/djangoapps/student/management/commands/6002exportusers.py |  4 ----
 common/djangoapps/student/management/commands/6002importusers.py |  4 ----
 common/djangoapps/student/management/commands/assigngroups.py    |  3 ---
 common/djangoapps/student/management/commands/emaillist.py       |  4 ----
 common/djangoapps/student/management/commands/massemail.py       |  8 +++-----
 common/djangoapps/student/management/commands/massemailtxt.py    |  8 +++-----
 common/djangoapps/student/management/commands/userinfo.py        |  3 ---
 common/lib/django_startup.py                                     |  2 +-
 lms/djangoapps/certificates/queue.py                             |  9 ---------
 lms/djangoapps/courseware/management/commands/check_course.py    |  2 --
 lms/djangoapps/courseware/tests/test_views.py                    |  5 +++++
 lms/djangoapps/instructor_task/tasks_helper.py                   | 21 ---------------------
 16 files changed, 54 insertions(+), 94 deletions(-)
 create mode 100644 common/djangoapps/mitxmako/startup.py

diff --git a/common/djangoapps/mitxmako/middleware.py b/common/djangoapps/mitxmako/middleware.py
index 5646d2f..daaddf6 100644
--- a/common/djangoapps/mitxmako/middleware.py
+++ b/common/djangoapps/mitxmako/middleware.py
@@ -12,36 +12,11 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
-from mako.lookup import TemplateLookup
-import tempdir
 from django.template import RequestContext
-from django.conf import settings
 
 requestcontext = None
-lookup = {}
-
 
 class MakoMiddleware(object):
-    def __init__(self):
-        """Setup mako variables and lookup object"""
-        # Set all mako variables based on django settings
-        template_locations = settings.MAKO_TEMPLATES
-        module_directory = getattr(settings, 'MAKO_MODULE_DIR', None)
-
-        if module_directory is None:
-            module_directory = tempdir.mkdtemp_clean()
-
-        for location in template_locations:
-            lookup[location] = TemplateLookup(directories=template_locations[location],
-                                module_directory=module_directory,
-                                output_encoding='utf-8',
-                                input_encoding='utf-8',
-                                default_filters=['decode.utf8'],
-                                encoding_errors='replace',
-                                )
-
-        import mitxmako
-        mitxmako.lookup = lookup
 
     def process_request(self, request):
         global requestcontext
diff --git a/common/djangoapps/mitxmako/shortcuts.py b/common/djangoapps/mitxmako/shortcuts.py
index 3c68fa8..974eaef 100644
--- a/common/djangoapps/mitxmako/shortcuts.py
+++ b/common/djangoapps/mitxmako/shortcuts.py
@@ -16,7 +16,7 @@ from django.template import Context
 from django.http import HttpResponse
 import logging
 
-from . import middleware
+import mitxmako
 from django.conf import settings
 from django.core.urlresolvers import reverse
 log = logging.getLogger(__name__)
@@ -80,15 +80,15 @@ def render_to_string(template_name, dictionary, context=None, namespace='main'):
     context_instance['marketing_link'] = marketing_link
 
     # In various testing contexts, there might not be a current request context.
-    if middleware.requestcontext is not None:
-        for d in middleware.requestcontext:
+    if mitxmako.middleware.requestcontext is not None:
+        for d in mitxmako.middleware.requestcontext:
             context_dictionary.update(d)
     for d in context_instance:
         context_dictionary.update(d)
     if context:
         context_dictionary.update(context)
     # fetch and render template
-    template = middleware.lookup[namespace].get_template(template_name)
+    template = mitxmako.lookup[namespace].get_template(template_name)
     return template.render_unicode(**context_dictionary)
 
 
diff --git a/common/djangoapps/mitxmako/startup.py b/common/djangoapps/mitxmako/startup.py
new file mode 100644
index 0000000..db9483b
--- /dev/null
+++ b/common/djangoapps/mitxmako/startup.py
@@ -0,0 +1,33 @@
+"""
+Initialize the mako template lookup
+"""
+
+import tempdir
+from django.conf import settings
+from mako.lookup import TemplateLookup
+
+import mitxmako
+
+
+def run():
+    """Setup mako variables and lookup object"""
+    # Set all mako variables based on django settings
+    template_locations = settings.MAKO_TEMPLATES
+    module_directory = getattr(settings, 'MAKO_MODULE_DIR', None)
+
+    if module_directory is None:
+        module_directory = tempdir.mkdtemp_clean()
+
+    lookup = {}
+
+    for location in template_locations:
+        lookup[location] = TemplateLookup(
+            directories=template_locations[location],
+            module_directory=module_directory,
+            output_encoding='utf-8',
+            input_encoding='utf-8',
+            default_filters=['decode.utf8'],
+            encoding_errors='replace',
+        )
+
+    mitxmako.lookup = lookup
diff --git a/common/djangoapps/mitxmako/template.py b/common/djangoapps/mitxmako/template.py
index 5becfbf..7dfc6de 100644
--- a/common/djangoapps/mitxmako/template.py
+++ b/common/djangoapps/mitxmako/template.py
@@ -16,7 +16,8 @@ from django.conf import settings
 from mako.template import Template as MakoTemplate
 from mitxmako.shortcuts import marketing_link
 
-from mitxmako import middleware
+import mitxmako
+import mitxmako.middleware
 
 django_variables = ['lookup', 'output_encoding', 'encoding_errors']
 
@@ -33,7 +34,7 @@ class Template(MakoTemplate):
     def __init__(self, *args, **kwargs):
         """Overrides base __init__ to provide django variable overrides"""
         if not kwargs.get('no_django', False):
-            overrides = dict([(k, getattr(middleware, k, None),) for k in django_variables])
+            overrides = dict([(k, getattr(mitxmako, k, None),) for k in django_variables])
             overrides['lookup'] = overrides['lookup']['main']
             kwargs.update(overrides)
         super(Template, self).__init__(*args, **kwargs)
@@ -47,8 +48,8 @@ class Template(MakoTemplate):
         context_dictionary = {}
 
         # In various testing contexts, there might not be a current request context.
-        if middleware.requestcontext is not None:
-            for d in middleware.requestcontext:
+        if mitxmako.middleware.requestcontext is not None:
+            for d in mitxmako.middleware.requestcontext:
                 context_dictionary.update(d)
         for d in context_instance:
             context_dictionary.update(d)
diff --git a/common/djangoapps/student/management/commands/6002exportusers.py b/common/djangoapps/student/management/commands/6002exportusers.py
index a92bb0a..a36d6e8 100644
--- a/common/djangoapps/student/management/commands/6002exportusers.py
+++ b/common/djangoapps/student/management/commands/6002exportusers.py
@@ -16,10 +16,6 @@ from django.contrib.auth.models import User
 
 from student.models import UserProfile
 
-import mitxmako.middleware as middleware
-
-middleware.MakoMiddleware()
-
 
 class Command(BaseCommand):
     help = \
diff --git a/common/djangoapps/student/management/commands/6002importusers.py b/common/djangoapps/student/management/commands/6002importusers.py
index 1f98bd7..93d86df 100644
--- a/common/djangoapps/student/management/commands/6002importusers.py
+++ b/common/djangoapps/student/management/commands/6002importusers.py
@@ -12,10 +12,6 @@ from django.contrib.auth.models import User
 
 from student.models import UserProfile
 
-import mitxmako.middleware as middleware
-
-middleware.MakoMiddleware()
-
 
 def import_user(u):
     user_info = u['u']
diff --git a/common/djangoapps/student/management/commands/assigngroups.py b/common/djangoapps/student/management/commands/assigngroups.py
index 3e36bf3..cbd5cfa 100644
--- a/common/djangoapps/student/management/commands/assigngroups.py
+++ b/common/djangoapps/student/management/commands/assigngroups.py
@@ -1,7 +1,6 @@
 from django.core.management.base import BaseCommand
 from django.contrib.auth.models import User
 
-import mitxmako.middleware as middleware
 from student.models import UserTestGroup
 
 import random
@@ -11,8 +10,6 @@ import datetime
 import json
 from pytz import UTC
 
-middleware.MakoMiddleware()
-
 
 def group_from_value(groups, v):
     ''' Given group: (('a',0.3),('b',0.4),('c',0.3)) And random value
diff --git a/common/djangoapps/student/management/commands/emaillist.py b/common/djangoapps/student/management/commands/emaillist.py
index d391192..e69b072 100644
--- a/common/djangoapps/student/management/commands/emaillist.py
+++ b/common/djangoapps/student/management/commands/emaillist.py
@@ -1,10 +1,6 @@
 from django.core.management.base import BaseCommand
 from django.contrib.auth.models import User
 
-import mitxmako.middleware as middleware
-
-middleware.MakoMiddleware()
-
 
 class Command(BaseCommand):
     help = \
diff --git a/common/djangoapps/student/management/commands/massemail.py b/common/djangoapps/student/management/commands/massemail.py
index 1bb65fd..a1864f0 100644
--- a/common/djangoapps/student/management/commands/massemail.py
+++ b/common/djangoapps/student/management/commands/massemail.py
@@ -1,9 +1,7 @@
 from django.core.management.base import BaseCommand
 from django.contrib.auth.models import User
 
-import mitxmako.middleware as middleware
-
-middleware.MakoMiddleware()
+import mitxmako
 
 
 class Command(BaseCommand):
@@ -17,8 +15,8 @@ body, and an _subject.txt for the subject. '''
         #text = open(args[0]).read()
         #subject = open(args[1]).read()
         users = User.objects.all()
-        text = middleware.lookup['main'].get_template('email/' + args[0] + ".txt").render()
-        subject = middleware.lookup['main'].get_template('email/' + args[0] + "_subject.txt").render().strip()
+        text = mitxmako.lookup['main'].get_template('email/' + args[0] + ".txt").render()
+        subject = mitxmako.lookup['main'].get_template('email/' + args[0] + "_subject.txt").render().strip()
         for user in users:
             if user.is_active:
                 user.email_user(subject, text)
diff --git a/common/djangoapps/student/management/commands/massemailtxt.py b/common/djangoapps/student/management/commands/massemailtxt.py
index ae25430..0228acf 100644
--- a/common/djangoapps/student/management/commands/massemailtxt.py
+++ b/common/djangoapps/student/management/commands/massemailtxt.py
@@ -4,15 +4,13 @@ import time
 from django.core.management.base import BaseCommand
 from django.conf import settings
 
-import mitxmako.middleware as middleware
+import mitxmako
 
 from django.core.mail import send_mass_mail
 import sys
 
 import datetime
 
-middleware.MakoMiddleware()
-
 
 def chunks(l, n):
     """ Yield successive n-sized chunks from l.
@@ -41,8 +39,8 @@ rate -- messages per second
 
         users = [u.strip() for u in open(user_file).readlines()]
 
-        message = middleware.lookup['main'].get_template('emails/' + message_base + "_body.txt").render()
-        subject = middleware.lookup['main'].get_template('emails/' + message_base + "_subject.txt").render().strip()
+        message = mitxmako.lookup['main'].get_template('emails/' + message_base + "_body.txt").render()
+        subject = mitxmako.lookup['main'].get_template('emails/' + message_base + "_subject.txt").render().strip()
         rate = int(ratestr)
 
         self.log_file = open(logfilename, "a+", buffering=0)
diff --git a/common/djangoapps/student/management/commands/userinfo.py b/common/djangoapps/student/management/commands/userinfo.py
index 5467db1..8656fb9 100644
--- a/common/djangoapps/student/management/commands/userinfo.py
+++ b/common/djangoapps/student/management/commands/userinfo.py
@@ -1,13 +1,10 @@
 from django.core.management.base import BaseCommand
 from django.contrib.auth.models import User
 
-import mitxmako.middleware as middleware
 import json
 
 from student.models import UserProfile
 
-middleware.MakoMiddleware()
-
 
 class Command(BaseCommand):
     help = \
diff --git a/common/lib/django_startup.py b/common/lib/django_startup.py
index 1987d02..1432ea0 100644
--- a/common/lib/django_startup.py
+++ b/common/lib/django_startup.py
@@ -7,7 +7,7 @@ def autostartup():
     """
     for app in settings.INSTALLED_APPS:
         try:
-            mod = import_module('{}.startup')
+            mod = import_module(app + '.startup')
             if hasattr(mod, 'run'):
                 mod.run()
         except ImportError:
diff --git a/lms/djangoapps/certificates/queue.py b/lms/djangoapps/certificates/queue.py
index 78e786e..bc7bbc0 100644
--- a/lms/djangoapps/certificates/queue.py
+++ b/lms/djangoapps/certificates/queue.py
@@ -3,7 +3,6 @@ from certificates.models import certificate_status_for_student
 from certificates.models import CertificateStatuses as status
 from certificates.models import CertificateWhitelist
 
-from mitxmako.middleware import MakoMiddleware
 from courseware import grades, courses
 from django.test.client import RequestFactory
 from capa.xqueue_interface import XQueueInterface
@@ -52,14 +51,6 @@ class XQueueCertInterface(object):
     """
 
     def __init__(self, request=None):
-        # MakoMiddleware Note:
-        # Line below has the side-effect of writing to a module level lookup
-        # table that will allow problems to render themselves. If this is not
-        # present, problems that a student hasn't seen will error when loading,
-        # causing the grading system to under-count the possible score and
-        # inflate their grade. This dependency is bad and was probably recently
-        # introduced. This is the bandage until we can trace the root cause.
-        m = MakoMiddleware()
 
         # Get basic auth (username/password) for
         # xqueue connection if it's in the settings
diff --git a/lms/djangoapps/courseware/management/commands/check_course.py b/lms/djangoapps/courseware/management/commands/check_course.py
index 58f8933..a4f2bcc 100644
--- a/lms/djangoapps/courseware/management/commands/check_course.py
+++ b/lms/djangoapps/courseware/management/commands/check_course.py
@@ -10,8 +10,6 @@ from django.contrib.auth.models import User
 
 import xmodule
 
-import mitxmako.middleware as middleware
-middleware.MakoMiddleware()
 from xmodule.modulestore.django import modulestore
 from courseware.model_data import ModelDataCache
 from courseware.module_render import get_module
diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py
index c6c382c..b4e835d 100644
--- a/lms/djangoapps/courseware/tests/test_views.py
+++ b/lms/djangoapps/courseware/tests/test_views.py
@@ -12,6 +12,7 @@ from django.core.urlresolvers import reverse
 
 from student.models import CourseEnrollment
 from student.tests.factories import AdminFactory
+from mitxmako.middleware import MakoMiddleware
 
 from xmodule.modulestore.django import modulestore
 
@@ -135,6 +136,10 @@ class ViewsTestCase(TestCase):
     def verify_end_date(self, course_id, expected_end_text=None):
         request = self.request_factory.get("foo")
         request.user = self.user
+
+        # TODO: Remove the dependency on MakoMiddleware (by making the views explicitly supply a RequestContext)
+        MakoMiddleware().process_request(request)
+
         result = views.course_about(request, course_id)
         if expected_end_text is not None:
             self.assertContains(result, "Classes End")
diff --git a/lms/djangoapps/instructor_task/tasks_helper.py b/lms/djangoapps/instructor_task/tasks_helper.py
index c5a9b4d..6ee72ec 100644
--- a/lms/djangoapps/instructor_task/tasks_helper.py
+++ b/lms/djangoapps/instructor_task/tasks_helper.py
@@ -20,7 +20,6 @@ from dogapi import dog_stats_api
 
 from xmodule.modulestore.django import modulestore
 
-import mitxmako.middleware as middleware
 from track.views import task_track
 
 from courseware.models import StudentModule
@@ -35,26 +34,6 @@ TASK_LOG = get_task_logger(__name__)
 UNKNOWN_TASK_ID = 'unknown-task_id'
 
 
-def initialize_mako(sender=None, conf=None, **kwargs):
-    """
-    Get mako templates to work on celery worker server's worker thread.
-
-    The initialization of Mako templating is usually done when Django is
-    initializing middleware packages as part of processing a server request.
-    When this is run on a celery worker server, no such initialization is
-    called.
-
-    To make sure that we don't load this twice (just in case), we look for the
-    result: the defining of the lookup paths for templates.
-    """
-    if 'main' not in middleware.lookup:
-        TASK_LOG.info("Initializing Mako middleware explicitly")
-        middleware.MakoMiddleware()
-
-# Actually make the call to define the hook:
-worker_process_init.connect(initialize_mako)
-
-
 class UpdateProblemModuleStateError(Exception):
     """
     Error signaling a fatal condition while updating problem modules.
--
libgit2 0.26.0