Commit 28e63d4f by Carl Whittaker

Adding template Loader class

parent 01dd06b3
from pystache.template import Template from pystache.template import Template
from pystache.view import View from pystache.view import View
from pystache.loader import Loader
def render(template, context=None, **kwargs): def render(template, context=None, **kwargs):
context = context and context.copy() or {} context = context and context.copy() or {}
......
import os
class Loader(object):
template_extension = 'mustache'
template_path = '.'
template_encoding = None
def load_template(self, template_name, template_dirs=None):
'''Returns the template string from a file or throws IOError if it non existent'''
if None == template_dirs:
template_dirs = self.template_path
file_name = template_name + '.' + self.template_extension
# Given a single directory we'll load from it
if isinstance(template_dirs, basestring):
file_path = os.path.join(template_dirs, file_name)
return self._load_template_file(file_path)
# Given a list of directories we'll check each for our file
for path in template_dirs:
file_path = os.path.join(path, file_name)
if os.path.exists(file_path):
return self._load_template_file(file_path)
raise IOError('"%s" not found in "%s"' % (template_name, ':'.join(template_dirs),))
def _load_template_file(self, file_path):
'''Loads and returns the template file from disk'''
f = open(file_path, 'r')
try:
template = f.read()
if self.template_encoding:
template = unicode(template, self.template_encoding)
finally:
f.close()
return template
\ No newline at end of file
import re import re
import cgi import cgi
import collections import collections
import os
modifiers = {} modifiers = {}
def modifier(symbol): def modifier(symbol):
...@@ -107,6 +108,7 @@ class Template(object): ...@@ -107,6 +108,7 @@ class Template(object):
insides = [] insides = []
for item in listing: for item in listing:
view = View(context=item) view = View(context=item)
view.template_path = self.view.template_path
view.parent = self.view view.parent = self.view
insides.append(Template(template, view).render()) insides.append(Template(template, view).render())
...@@ -117,6 +119,12 @@ class Template(object): ...@@ -117,6 +119,12 @@ class Template(object):
raw = view.get(tag_name, '') raw = view.get(tag_name, '')
return cgi.escape(unicode(raw)) return cgi.escape(unicode(raw))
@modifier('>')
def _render_partial(self, template_name, view):
# mothereffin template loader goes here
template = view.get_template(template_name)
return Template(template, view).render()
def render(self): def render(self):
template = self._render_sections(self.template, self.view) template = self._render_sections(self.template, self.view)
......
...@@ -5,6 +5,10 @@ from types import * ...@@ -5,6 +5,10 @@ from types import *
class View(object): class View(object):
template_name = None
template_path = None
template = None
def __init__(self, template=None, context=None, **kwargs): def __init__(self, template=None, context=None, **kwargs):
self.template = template self.template = template
self.context = context or {} self.context = context or {}
...@@ -22,4 +26,31 @@ class View(object): ...@@ -22,4 +26,31 @@ class View(object):
if hasattr(self, 'parent'): if hasattr(self, 'parent'):
return self.parent.get(attr, default) return self.parent.get(attr, default)
else: else:
return default return default
\ No newline at end of file
def get_template(self, template_name):
if not self.template:
from pystache import Loader
template_name = self._get_template_name(template_name)
self.template = Loader().load_template(template_name, self.template_path)
return self.template
def _get_template_name(self, template_name=None):
"""TemplatePartial => template_partial
Takes a string but defaults to using the current class' name or
the `template_name` attribute
"""
if self.template_name:
return self.template_name
if not template_name:
template_name = self.__class__.__name__
def repl(match):
return '_' + match.group(0).lower()
return re.sub('[A-Z]', repl, template_name)[1:]
def render(self):
return Template(self.get_template(self.template_name), self).render()
\ No newline at end of file
import unittest
import pystache
class TestLoader(unittest.TestCase):
def test_template_is_loaded(self):
loader = pystache.Loader()
template = loader.load_template('simple', 'examples')
self.assertEqual(template, 'Hi {{thing}}!{{blank}}')
def test_using_list_of_paths(self):
loader = pystache.Loader()
template = loader.load_template('simple', ['doesnt_exist', 'examples'])
self.assertEqual(template, 'Hi {{thing}}!{{blank}}')
def test_non_existent_template_fails(self):
loader = pystache.Loader()
self.assertRaises(IOError, loader.load_template, 'simple', 'doesnt_exist')
\ No newline at end of file
...@@ -3,13 +3,12 @@ import pystache ...@@ -3,13 +3,12 @@ import pystache
from examples.nested_context import NestedContext from examples.nested_context import NestedContext
from examples.complex_view import ComplexView from examples.complex_view import ComplexView
from examples.lambdas import Lambdas from examples.lambdas import Lambdas
from examples.template_partial import TemplatePartial
class TestSimple(unittest.TestCase): class TestSimple(unittest.TestCase):
def test_simple_render(self): def test_simple_render(self):
tmpl = '{{derp}}' self.assertEqual('herp', pystache.Template('{{derp}}', {'derp': 'herp'}).render())
self.assertEqual('herp', pystache.Template(tmpl, {'derp': 'herp'}).render())
def test_nested_context(self): def test_nested_context(self):
view = NestedContext() view = NestedContext()
...@@ -25,4 +24,10 @@ class TestSimple(unittest.TestCase): ...@@ -25,4 +24,10 @@ class TestSimple(unittest.TestCase):
def test_callables(self): def test_callables(self):
view = Lambdas() view = Lambdas()
self.assertEquals(pystache.Template('{{#replace_foo_with_bar}}foo != bar. oh, it does!{{/replace_foo_with_bar}}', view).render(), 'bar != bar. oh, it does!') self.assertEquals(pystache.Template('{{#replace_foo_with_bar}}foo != bar. oh, it does!{{/replace_foo_with_bar}}', view).render(), 'bar != bar. oh, it does!')
\ No newline at end of file
def test_rendering_partial(self):
view = TemplatePartial()
self.assertEquals(pystache.Template('{{>inner_partial}}', view).render(), 'Again, Welcome!')
self.assertEquals(pystache.Template('{{#looping}}{{>inner_partial}} {{/looping}}', view).render(), 'Again, Welcome! Again, Welcome! Again, Welcome! ')
\ No newline at end of file
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