Commit 16ce94a2 by Carl Whittaker

Moving context logic into view

parent ac941e56
<h1>{{ header }}</h1>
{{#list}}
<ul>
{{#item}}
{{# current }}
<li><strong>{{name}}</strong></li>
{{/ current }}
{{#link}}
<li><a href="{{url}}">{{name}}</a></li>
{{/link}}
{{/item}}
</ul>
{{/list}}
{{#empty}}
<p>The list is empty.</p>
{{/empty}}
\ No newline at end of file
<h1>{{ header }}</h1>{{#list}}<ul>{{#item}}{{# current }}<li><strong>{{name}}</strong></li>{{/ current }}{{#link}}<li><a href="{{url}}">{{name}}</a></li>{{/link}}{{/item}}</ul>{{/list}}{{#empty}}<p>The list is empty.</p>{{/empty}}
\ No newline at end of file
{{#t}}
* first
{{/t}}
{{#t}}* first{{/t}}
* {{two}}
{{#t}}
* third
{{/t}}
\ No newline at end of file
{{#t}}* third{{/t}}
\ No newline at end of file
{{#replace_foo_with_bar}}
foo != bar. oh, it does!
{{/replace_foo_with_bar}}
\ No newline at end of file
{{#replace_foo_with_bar}}foo != bar. oh, it does!{{/replace_foo_with_bar}}
\ No newline at end of file
......@@ -19,21 +19,21 @@ def modifier(symbol):
return func
return set_modifier
def get_or_attr(context_list, name, default=None):
if not context_list:
return default
for obj in context_list:
try:
return obj[name]
except KeyError:
pass
except:
try:
return getattr(obj, name)
except AttributeError:
pass
return default
# def get_or_attr(context_list, name, default=None):
# if not context_list:
# return default
#
# for obj in context_list:
# try:
# return obj[name]
# except KeyError:
# pass
# except:
# try:
# return getattr(obj, name)
# except AttributeError:
# pass
# return default
class Template(object):
......@@ -52,7 +52,6 @@ class Template(object):
context.update(kwargs)
self.view = context if isinstance(context, View) else View(context=context)
self.context_list = [self.view]
self._compile_regexps()
def _compile_regexps(self):
......@@ -76,7 +75,7 @@ class Template(object):
section, section_name, inner = match.group(0, 1, 2)
section_name = section_name.strip()
it = get_or_attr(self.context_list, section_name, None)
it = self.view.get(section_name, None)
replacer = ''
# Callable
......@@ -113,11 +112,10 @@ class Template(object):
return template
def _render_dictionary(self, template, context):
self.view.context_list.insert(0, context)
template = Template(template, self.view)
self.context_list.insert(0, context)
template.context_list = self.context_list
out = template.render()
self.context_list.pop(0)
self.view.context_list.pop(0)
return out
def _render_list(self, template, listing):
......@@ -129,7 +127,7 @@ class Template(object):
@modifier(None)
def _render_tag(self, tag_name):
raw = get_or_attr(self.context_list, tag_name, '')
raw = self.view.get(tag_name, '')
# For methods with no return value
if not raw and raw is not 0:
......@@ -147,7 +145,7 @@ class Template(object):
markup = Loader().load_template(template_name, self.view.template_path, encoding=self.view.template_encoding)
template = Template(markup, self.view)
template.context_list = self.context_list
# template.context_list = self.context_list
return template.render()
@modifier('=')
......
......@@ -3,6 +3,22 @@ import os.path
import re
from types import *
def get_or_attr(context_list, name, default=None):
if not context_list:
return default
for obj in context_list:
try:
return obj[name]
except KeyError:
pass
except:
try:
return getattr(obj, name)
except AttributeError:
pass
return default
class View(object):
template_name = None
......@@ -13,15 +29,15 @@ class View(object):
def __init__(self, template=None, context=None, **kwargs):
self.template = template
self.context = context or {}
self.context.update(**kwargs)
context = context or {}
context.update(**kwargs)
self.context_list = [context]
def get(self, attr, default=None):
attr = self.context.get(attr, getattr(self, attr, default))
attr = get_or_attr(self.context_list, attr, getattr(self, attr, default))
if hasattr(attr, '__call__') and type(attr) is UnboundMethodType:
return attr()
if hasattr(attr, 'render'):
return attr.render(encoding=self.template_encoding)
else:
return attr
......@@ -48,7 +64,7 @@ class View(object):
return re.sub('[A-Z]', repl, template_name)[1:]
def render(self, encoding=None):
def render(self, encoding=None):
return Template(self.get_template(self.template_name), self).render(encoding=encoding)
def __contains__(self, needle):
......@@ -56,9 +72,10 @@ class View(object):
def __getitem__(self, attr):
val = self.get(attr, None)
if not val and val is not 0:
raise KeyError("No such key.")
return val
return val
def __str__(self):
return self.render()
\ No newline at end of file
......@@ -19,9 +19,7 @@ class TestView(unittest.TestCase):
""")
def test_double_section(self):
self.assertEquals(DoubleSection().render(), """* first
* second
* third""")
self.assertEquals(DoubleSection().render(),"""* first\n* second\n* third""")
def test_unicode_output(self):
self.assertEquals(UnicodeOutput().render(), u'<p>Name: Henri Poincaré</p>')
......@@ -77,8 +75,7 @@ Again, Welcome!
self.assertEquals(view.render(), 'it works!')
def test_partial_in_partial_has_access_to_grand_parent_context(self):
view = TemplatePartial()
view.context = {'prop': 'derp'}
view = TemplatePartial(context = {'prop': 'derp'})
view.template = '''{{>partial_in_partial}}'''
self.assertEquals(view.render(), 'Hi derp!')
......
......@@ -63,21 +63,11 @@ class TestPystache(unittest.TestCase):
self.assertEquals(ret, u'Name: Henri Poincaré; Age: 156')
def test_sections(self):
template = """
<ul>
{{#users}}
<li>{{name}}</li>
{{/users}}
</ul>
"""
template = """<ul>{{#users}}<li>{{name}}</li>{{/users}}</ul>"""
context = { 'users': [ {'name': 'Chris'}, {'name': 'Tom'}, {'name': 'PJ'} ] }
ret = pystache.render(template, context)
self.assertEquals(ret, """
<ul>
<li>Chris</li><li>Tom</li><li>PJ</li>
</ul>
""")
self.assertEquals(ret, """<ul><li>Chris</li><li>Tom</li><li>PJ</li></ul>""")
if __name__ == '__main__':
unittest.main()
......@@ -54,12 +54,8 @@ class TestView(unittest.TestCase):
self.assertEquals(view.render(), "Hi chris!")
def test_complex(self):
self.assertEquals(ComplexView().render(), """<h1>Colors</h1>
<ul>
<li><strong>red</strong></li>\n \n <li><a href="#Green">green</a></li>
<li><a href="#Blue">blue</a></li>
</ul>
""")
self.assertEquals(ComplexView().render(),
"""<h1>Colors</h1><ul><li><strong>red</strong></li><li><a href="#Green">green</a></li><li><a href="#Blue">blue</a></li></ul>""")
def test_higher_order_replace(self):
view = Lambdas()
......@@ -90,6 +86,11 @@ class TestView(unittest.TestCase):
view = Inverted()
self.assertEquals(view.render(), """one, two, three, empty list""")
# def test_accessing_properties_on_parent_view(self):
# view = Simple(context={'child':child})
# view.template = '{{#child}}{{#t}}{{thing}}{{/t}}{{/child}}'
#
# self.assertEquals(view.render(), 'pizza1')
if __name__ == '__main__':
unittest.main()
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