funkybob / stencil

A minimalist template engine for Python3
MIT License
58 stars 8 forks source link

Error "string indices must be integers" #24

Closed ernstki closed 2 weeks ago

ernstki commented 2 weeks ago

I did eventually figure this out, and it's probably not a bug, but it threw me off enough that I wonder if someone else won't run into this eventually, too. Documenting here purely for posterity.

This Template tries to print a key from a dictionary thing, which is assumed to be one of a list of things, obtained by iterating with a {% for %} construct. However, I made an error in defining the context, so there's no actual list (my real data structure was deeply-nested, so it was hard to spot, believe me).

So this

from stencil import Template, Context
t = Template("{% for thing in things %}{{ thing['key1'] }}{% endfor %}")
c1 = Context({'things': {'key1': 'value1'}})
t.render(c1)

results in

File path/to/stencil.py:154, in AstLookup.resolve(self, context)
    151 left = self.left.resolve(context)
    152 right = self.right.resolve(context)
--> 154 return left[right]

TypeError: string indices must be integers

whereas

c2 = Context({'things': [{'key1': 'value1'}]})
t.render(c2)

yields the expected thing

value1
funkybob commented 2 weeks ago

Indeed, the error message could have been more detailed about where the problem occurred.

Since dicts are iterable just like lists, you've wound up iterating over the keys from your things dict, which are strings.

ernstki commented 2 weeks ago

Ha, you're always on duty! Didn't even have time to answer my own question!

Looking at what happens here

from stencil import Template, Context
t = Template("{% for thing in things %}{{ thing }}{% endfor %}")
c1 = Context({'things': {'key1': 'value1'}})
t.render(c1)

which is

key1

…it's pretty clear what the mistake is, Python newbie stuff. I'd been spending a lot of time in another programming language lately, and I guess I'd forgotten (or never knew) that for _ in dict iterates over the keys in a dictionary. You'd have to do foreach my $_ (keys %hash) in that other language.

So the TypeError: string indices must be integers error message finally makes sense: you can't subscript a string with another string. Duh!

ernstki commented 2 weeks ago

Indeed, the error message could have been more detailed about where the problem occurred.

It's a bare-bones library, and I appreciate that. This one's on me, not you!