From 316c9d48307d197ded26c7c11e0c316488a0ddba Mon Sep 17 00:00:00 2001 From: Christian Metts Date: Tue, 26 Feb 2013 15:04:50 -0800 Subject: [PATCH 1/2] Allow finding specific list items by index. This matches the behavior of JS implementations of mustache. Tested against mustache.js and Hogan. >>> context = {"data": ['one', 'two', 'three']} >>> pystache.render("{{ data.0 }}", context) 'one' --- pystache/context.py | 12 +++++++++++- pystache/tests/test_context.py | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/pystache/context.py b/pystache/context.py index 67159160..744c492a 100644 --- a/pystache/context.py +++ b/pystache/context.py @@ -50,7 +50,17 @@ def _get_value(context, key): # (e.g. catching KeyError). if key in context: return context[key] - elif type(context).__module__ != _BUILTIN_MODULE: + if isinstance(context, list): + # If we're dealing with a list or a list subclass attempt to use the key + # as an index on the list. + # + # We pass on ValueError (the key is not an int) or IndexError (the key/int + # is not in the list). And continue with normal processing. + try: + return context[int(key)] + except (ValueError, IndexError): + pass + if type(context).__module__ != _BUILTIN_MODULE: # Then we consider the argument an "object" for the purposes of # the spec. # diff --git a/pystache/tests/test_context.py b/pystache/tests/test_context.py index 238e4b00..bcc7f4b8 100644 --- a/pystache/tests/test_context.py +++ b/pystache/tests/test_context.py @@ -221,6 +221,12 @@ class MyList(list): pass self.assertEqual(_get_value(item1, 'pop'), 2) self.assertNotFound(item2, 'pop') + # get list items by index + self.assertEqual(_get_value(item2, '0'), 1) + + # Don't throw errors if we pass a non-int to a list. + self.assertNotFound(item2, 'numberone') + class ContextStackTestCase(unittest.TestCase, AssertIsMixin, AssertStringMixin, AssertExceptionMixin): @@ -497,3 +503,10 @@ def bar(self): stack = ContextStack({"foo": Foo()}) self.assertEqual(stack.get(name), "Baz") + + def test_dot_notation__list(self): + name = "foo.1" + + # When any element in the path is callable, it should be automatically invoked + stack = ContextStack({"foo": ['Ignore me.', 'Choose me!']}) + self.assertEqual(stack.get(name), "Choose me!") From ed3e119ae4806ccf49ffb84acf8d0670c0ef0d53 Mon Sep 17 00:00:00 2001 From: Christian Metts Date: Tue, 26 Feb 2013 16:13:10 -0800 Subject: [PATCH 2/2] Remove incorrect comment and add a docstring --- pystache/tests/test_context.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pystache/tests/test_context.py b/pystache/tests/test_context.py index bcc7f4b8..f163e17d 100644 --- a/pystache/tests/test_context.py +++ b/pystache/tests/test_context.py @@ -505,8 +505,10 @@ def bar(self): self.assertEqual(stack.get(name), "Baz") def test_dot_notation__list(self): - name = "foo.1" + """ Test that an index interger after a dot correctly grabs the item + if the parent is a list. - # When any element in the path is callable, it should be automatically invoked + """ + name = "foo.1" stack = ContextStack({"foo": ['Ignore me.', 'Choose me!']}) self.assertEqual(stack.get(name), "Choose me!")