Skip to content

Commit

Permalink
Allow finding specific list items by index.
Browse files Browse the repository at this point in the history
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'
  • Loading branch information
mintchaos committed Feb 26, 2013
1 parent 6a54b9a commit 316c9d4
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
12 changes: 11 additions & 1 deletion pystache/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
#
Expand Down
13 changes: 13 additions & 0 deletions pystache/tests/test_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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!")

0 comments on commit 316c9d4

Please sign in to comment.