summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRodrigo Bernardo Pimentel <rbp@isnomore.net>2012-04-04 11:50:48 +0200
committerRodrigo Bernardo Pimentel <rbp@isnomore.net>2012-04-04 11:50:48 +0200
commitca2cd4c0651b7d6e2e9e999323af96815723e9f5 (patch)
treecfe523684912e0036db24c8820d5c9018fe02326
parentd23da511a54714aa7ba641aefb234a21a5c12d37 (diff)
parent02a2472def23f1760b30af56d4b67fa58f1b620a (diff)
downloadpystache-ca2cd4c0651b7d6e2e9e999323af96815723e9f5.tar.gz
Merge branch 'spec-1.1.2-compliant' into development
-rw-r--r--pystache/context.py5
-rw-r--r--tests/common.py17
-rw-r--r--tests/test_context.py38
-rw-r--r--tests/test_renderengine.py46
-rw-r--r--tests/test_simple.py20
5 files changed, 102 insertions, 24 deletions
diff --git a/pystache/context.py b/pystache/context.py
index 6e75c07..2ebf549 100644
--- a/pystache/context.py
+++ b/pystache/context.py
@@ -54,8 +54,9 @@ def _get_value(item, key):
value = attr
for part in parts[1:]:
- if value is not _NOT_FOUND:
- value = _get_value(value, part)
+ if value is _NOT_FOUND:
+ break
+ value = _get_value(value, part)
return value
diff --git a/tests/common.py b/tests/common.py
index adc3ec2..5d1ef5c 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -51,3 +51,20 @@ class AssertIsMixin:
# http://docs.python.org/library/unittest.html#unittest.TestCase.assertIsNone
def assertIs(self, first, second):
self.assertTrue(first is second, msg="%s is not %s" % (repr(first), repr(second)))
+
+
+class Attachable(object):
+ """A trivial object that attaches all constructor named parameters as attributes.
+ For instance,
+
+ >>> o = Attachable(foo=42, size="of the universe")
+ >>> o.foo
+ 42
+ >>> o.size
+ of the universe
+ """
+ def __init__(self, **kwargs):
+ for arg, value in kwargs.iteritems():
+ setattr(self, arg, value)
+
+
diff --git a/tests/test_context.py b/tests/test_context.py
index decf4fb..e216405 100644
--- a/tests/test_context.py
+++ b/tests/test_context.py
@@ -11,7 +11,7 @@ import unittest
from pystache.context import _NOT_FOUND
from pystache.context import _get_value
from pystache.context import Context
-from tests.common import AssertIsMixin
+from tests.common import AssertIsMixin, Attachable
class SimpleObject(object):
@@ -398,3 +398,39 @@ class ContextTests(unittest.TestCase, AssertIsMixin):
# Confirm the original is unchanged.
self.assertEquals(original.get(key), "buzz")
+ def test_dot_notation__dict(self):
+ key = "foo.bar"
+ original = Context({"foo": {"bar": "baz"}})
+ self.assertEquals(original.get(key), "baz")
+
+ # Works all the way down
+ key = "a.b.c.d.e.f.g"
+ original = Context({"a": {"b": {"c": {"d": {"e": {"f": {"g": "w00t!"}}}}}}})
+ self.assertEquals(original.get(key), "w00t!")
+
+ def test_dot_notation__user_object(self):
+ key = "foo.bar"
+ original = Context({"foo": Attachable(bar="baz")})
+ self.assertEquals(original.get(key), "baz")
+
+ # Works on multiple levels, too
+ key = "a.b.c.d.e.f.g"
+ Obj = Attachable
+ original = Context({"a": Obj(b=Obj(c=Obj(d=Obj(e=Obj(f=Obj(g="w00t!"))))))})
+ self.assertEquals(original.get(key), "w00t!")
+
+ def test_dot_notation__mixed_dict_and_obj(self):
+ key = "foo.bar.baz.bak"
+ original = Context({"foo": Attachable(bar={"baz": Attachable(bak=42)})})
+ self.assertEquals(original.get(key), 42)
+
+ def test_dot_notation__missing_attr_or_key(self):
+ key = "foo.bar.baz.bak"
+ original = Context({"foo": {"bar": {}}})
+ self.assertEquals(original.get(key), None)
+
+ original = Context({"foo": Attachable(bar=Attachable())})
+ self.assertEquals(original.get(key), None)
+
+
+
diff --git a/tests/test_renderengine.py b/tests/test_renderengine.py
index 6c2831a..7752161 100644
--- a/tests/test_renderengine.py
+++ b/tests/test_renderengine.py
@@ -11,7 +11,7 @@ import unittest
from pystache.context import Context
from pystache.parser import ParsingError
from pystache.renderengine import RenderEngine
-from tests.common import AssertStringMixin
+from tests.common import AssertStringMixin, Attachable
class RenderEngineTestCase(unittest.TestCase):
@@ -453,3 +453,47 @@ class RenderTests(unittest.TestCase, AssertStringMixin):
expected = u' {{foo}} '
self._assert_render(expected, '{{=$ $=}} {{foo}} ')
self._assert_render(expected, '{{=$ $=}} {{foo}} $={{ }}=$') # was yielding u' '.
+
+ def test_dot_notation(self):
+ """
+ Check that we can use dot notation when the variable is a dict,
+ a used-defined object, or a combination of both
+ """
+ template = 'Hello, {{person.name}}. I see you are {{person.details.age}}.'
+ person = Attachable(name='Biggles', details={'age': 42})
+ context = {'person': person}
+ self._assert_render(u'Hello, Biggles. I see you are 42.', template, context)
+
+ def test_dot_notation__missing_attributes_or_keys(self):
+ """
+ Check that, when using dot notation, if the key or attribute does not
+ exist then its value is rendered as empty
+ """
+ template = """I cannot see {{person.name}}'s age: {{person.age}}.
+ Nor {{other_person.name}}'s: ."""
+ expected = u"""I cannot see Biggles's age: .
+ Nor Mr. Bradshaw's: ."""
+ context = {'person': {'name': 'Biggles'},
+ 'other_person': Attachable(name='Mr. Bradshaw')}
+ self._assert_render(expected, template, context)
+
+ def test_dot_notation__multiple_levels(self):
+ """
+ Check that using multiple levels of dot attributes works as expected
+ """
+ template = """Hello, Mr. {{person.name.lastname}}.
+ I see you're back from {{person.travels.last.country.city}}.
+ I'm missing some of your details: {{person.details.private.editor}}."""
+ expected = u"""Hello, Mr. Pither.
+ I see you're back from Cornwall.
+ I'm missing some of your details: ."""
+ context = {'person': {'name': {'firstname': 'unknown', 'lastname': 'Pither'},
+ 'travels': {'last': {'country': {'city': 'Cornwall'}}},
+ 'details': {'public': 'likes cycling'}}}
+ self._assert_render(expected, template, context)
+
+ # It should also work with user-defined objects
+ context = {'person': Attachable(name={'firstname': 'unknown', 'lastname': 'Pither'},
+ travels=Attachable(last=Attachable(country=Attachable(city='Cornwall'))),
+ details=Attachable())}
+ self._assert_render(expected, template, context)
diff --git a/tests/test_simple.py b/tests/test_simple.py
index 7dd6f53..a8fc815 100644
--- a/tests/test_simple.py
+++ b/tests/test_simple.py
@@ -60,26 +60,6 @@ class TestSimple(unittest.TestCase, AssertStringMixin):
template = '{{not_set}} {{blank}}'
self.assertEquals(pystache.Renderer().render(template), ' ')
- def test_dot_notation_with_dict(self):
- template = 'Name: {{person.name}}. Age: {{person.details.age}}. Intimate details (should be empty): {{person.details.intimate}}.'
- renderer = Renderer()
- context = {'person': {'name': 'Biggles', 'details': {'age': 42}}}
- actual = renderer.render(template, context)
- self.assertEquals(actual, 'Name: Biggles. Age: 42. Intimate details (should be empty): .')
-
- def test_dot_notation_with_user_objects(self):
- template = 'Name: {{person.name}}. Age: {{person.details.age}}. Intimate details (should be empty): {{person.details.intimate}}.'
- renderer = Renderer()
-
- class Person(object):
- def __init__(self, name, details):
- self.name = name
- self.details = details
-
- context = {'person': Person('Biggles', {'age': 42})}
- actual = renderer.render(template, context)
- self.assertEquals(actual, 'Name: Biggles. Age: 42. Intimate details (should be empty): .')
-
def test_template_partial_extension(self):
"""
Side note: