Commit 75967bd2 by Piotr Mitros

Render code isolated to analytics modules

parent 4c6d6e0c
### HACK HACK HACK ###
#
# This is a horrible hack to make a render() function for modules.
#
# In the future, each module should run within its own space
# (globals(), locals()), but for now, this kind of works.
#
# This code:
# 1. Looks at the stack to figure out the calling module
# 2. Matches that up to a module in INSTALLED_ANALYTICS_MODULE (based
# on longest matching path)
# 3. Uses pkg_resources to find the place where templates are
# stored (this is part of setuptools)
# 4. Renders the template with Mako
#
# I apologize about this code, but the alternative would be to
# ship without this, in which case we'd accrue technical debt
# with each new module written.
#
### HACK HACK HACK ###
import atexit
import importlib
import os.path
import shutil
import sys
import tempfile
import traceback
from pkg_resources import resource_filename
from mako.lookup import TemplateLookup
from django.conf import settings
## Code borrowed from mitx/common/lib/tempdir
def mkdtemp_clean(suffix="", prefix="tmp", dir=None):
"""Just like mkdtemp, but the directory will be deleted when the process ends."""
the_dir = tempfile.mkdtemp(suffix=suffix, prefix=prefix, dir=dir)
atexit.register(cleanup_tempdir, the_dir)
return the_dir
def cleanup_tempdir(the_dir):
"""Called on process exit to remove a temp directory."""
if os.path.exists(the_dir):
shutil.rmtree(the_dir)
module_directory = getattr(settings, 'MAKO_MODULE_DIR', None)
if module_directory is None:
module_directory = mkdtemp_clean()
lookups = {}
def lookup(directory):
if directory in lookups:
return lookups[directory]
else:
l = TemplateLookup(directories = [directory],
module_directory = module_directory,
output_encoding='utf-8',
input_encoding='utf-8',
encoding_errors='replace')
lookups[directory] = l
return l
def render(templatefile, context, caller = None):
stack = traceback.extract_stack()
if not caller:
caller_path = os.path.abspath(stack[-2][0])
# For testing, use: sys.modules.keys() if sys.modules[module] and '__file__' in sys.modules[module].__dict__]#
analytics_modules = [sys.modules[module] for module in settings.INSTALLED_ANALYTICS_MODULES]
analytics_modules.sort(key = lambda x : len(os.path.commonprefix([x.__file__, os.path.abspath(caller_path)])))
caller_module = analytics_modules[-1]
caller_name = caller_module.__name__
template_directory = os.path.abspath(resource_filename(caller_name, "templates"))
print "Caller, ", template_directory
template = lookup(template_directory).get_template(templatefile)
return template.render_unicode(**context)
return "Hello!"
...@@ -83,8 +83,8 @@ def handle_view(request, category, name, **kwargs): ...@@ -83,8 +83,8 @@ def handle_view(request, category, name, **kwargs):
Category is where this should be place (per student, per problem, etc.) Category is where this should be place (per student, per problem, etc.)
Name is specific Name is specific
''' '''
if not request.user.is_authenticated(): # if not request.user.is_authenticated():
return HttpResponseRedirect(reverse('django.contrib.auth.views.login')) # return HttpResponseRedirect(reverse('django.contrib.auth.views.login'))
return HttpResponse(handle_request(request, 'view', category, name, **kwargs)) return HttpResponse(handle_request(request, 'view', category, name, **kwargs))
......
...@@ -4,7 +4,12 @@ ...@@ -4,7 +4,12 @@
modules_to_import = [] modules_to_import = []
from djanalytics.core.decorators import query, event_handler from djanalytics.core.decorators import query, event_handler, view
@view()
def hello_template():
from djanalytics.core.render import render
return render("hello.html", {})
@query() @query()
def event_count(db): def event_count(db):
......
...@@ -93,3 +93,7 @@ class SimpleTest(TestCase): ...@@ -93,3 +93,7 @@ class SimpleTest(TestCase):
self.send_event(c, { 'filename' : "foo4.txt", 'fs_forgets_expiry' : -15}) self.send_event(c, { 'filename' : "foo4.txt", 'fs_forgets_expiry' : -15})
expire_objects() expire_objects()
verify({"foo1.txt":False, "foo2.txt":False, "foo3.txt":False, "foo4.txt":False}) verify({"foo1.txt":False, "foo2.txt":False, "foo3.txt":False, "foo4.txt":False})
def test_render(self):
c = Client()
self.assertEqual(c.get('/view/global/hello_template').content, open('modules/testmodule/templates/hello.html').read())
...@@ -22,7 +22,7 @@ DJFS = { 'type' : 'osfs', ...@@ -22,7 +22,7 @@ DJFS = { 'type' : 'osfs',
TIME_BETWEEN_DATA_REGENERATION = datetime.timedelta(minutes=1) TIME_BETWEEN_DATA_REGENERATION = datetime.timedelta(minutes=1)
INSTALLED_ANALYTICS_MODULES = ('modules.testmodule',) INSTALLED_ANALYTICS_MODULES = ('djanalytics.modules.testmodule',)
#Initialize celery #Initialize celery
import djcelery import djcelery
......
...@@ -37,8 +37,8 @@ if settings.DEBUG and settings.DJFS['type'] == 'osfs': ...@@ -37,8 +37,8 @@ if settings.DEBUG and settings.DJFS['type'] == 'osfs':
'show_indexes' : True, 'show_indexes' : True,
}), }),
) )
else: # else:
urlpatterns+= patterns('frontend.views', # urlpatterns+= patterns('frontend.views',
url(r'^data/(?P<path>.*)$', 'protected_data') # url(r'^data/(?P<path>.*)$', 'protected_data')
) # )
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment