mirror of
https://github.com/kennethreitz-archive/pystache.git
synced 2026-06-05 23:40:16 +00:00
Adding template Loader class
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from pystache.template import Template
|
||||
from pystache.view import View
|
||||
from pystache.loader import Loader
|
||||
|
||||
def render(template, context=None, **kwargs):
|
||||
context = context and context.copy() or {}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
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
|
||||
@@ -1,6 +1,7 @@
|
||||
import re
|
||||
import cgi
|
||||
import collections
|
||||
import os
|
||||
|
||||
modifiers = {}
|
||||
def modifier(symbol):
|
||||
@@ -107,6 +108,7 @@ class Template(object):
|
||||
insides = []
|
||||
for item in listing:
|
||||
view = View(context=item)
|
||||
view.template_path = self.view.template_path
|
||||
view.parent = self.view
|
||||
insides.append(Template(template, view).render())
|
||||
|
||||
@@ -117,6 +119,12 @@ class Template(object):
|
||||
raw = view.get(tag_name, '')
|
||||
|
||||
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):
|
||||
template = self._render_sections(self.template, self.view)
|
||||
|
||||
+32
-1
@@ -5,6 +5,10 @@ from types import *
|
||||
|
||||
class View(object):
|
||||
|
||||
template_name = None
|
||||
template_path = None
|
||||
template = None
|
||||
|
||||
def __init__(self, template=None, context=None, **kwargs):
|
||||
self.template = template
|
||||
self.context = context or {}
|
||||
@@ -22,4 +26,31 @@ class View(object):
|
||||
if hasattr(self, 'parent'):
|
||||
return self.parent.get(attr, default)
|
||||
else:
|
||||
return default
|
||||
return default
|
||||
|
||||
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()
|
||||
@@ -0,0 +1,21 @@
|
||||
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')
|
||||
@@ -3,13 +3,12 @@ import pystache
|
||||
from examples.nested_context import NestedContext
|
||||
from examples.complex_view import ComplexView
|
||||
from examples.lambdas import Lambdas
|
||||
from examples.template_partial import TemplatePartial
|
||||
|
||||
class TestSimple(unittest.TestCase):
|
||||
|
||||
def test_simple_render(self):
|
||||
tmpl = '{{derp}}'
|
||||
|
||||
self.assertEqual('herp', pystache.Template(tmpl, {'derp': 'herp'}).render())
|
||||
self.assertEqual('herp', pystache.Template('{{derp}}', {'derp': 'herp'}).render())
|
||||
|
||||
def test_nested_context(self):
|
||||
view = NestedContext()
|
||||
@@ -25,4 +24,10 @@ class TestSimple(unittest.TestCase):
|
||||
|
||||
def test_callables(self):
|
||||
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!')
|
||||
|
||||
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! ')
|
||||
Reference in New Issue
Block a user