noahmorrison/chevron

False-like values are not rendered when iterating

jrcutler opened this issue · 9 comments

It appears that False-like values (e.g. False, 0, 0.0, '', and []) are not being rendered correctly when iterating.

Example:

import chevron
template = '{{#.}}({{.}}){{/.}}{{^.}}empty{{/.}}'
data = [ False, 0, 0.0, '', [] ]
output = chevron.render(template, data)
print(repr(output))

Expected result: '(False)(0)(0.0)()([])'

Actual result: ''

(The fact that the specification doesn't test False-like values in the "Implicit Iterators" block of sections.yml is probably an upstream bug.)

Just took a few minutes testing it out, and yeah it looks like you found another hole in the spec.

I'm pretty sure the expected result should be (False)(0)(0.0)()() due to this test and it's what mustache.io outputs as well.

Am I wrong in thinking that? Or is the list printing as an empty list expected as well?

Well simply telling it that it shouldn't do falsy handling when inside a list doesn't cut it.

        # If the current scope is falsy and not the only scope
        elif not current_scope and len(scopes) != 1 and not (
            isinstance(scopes[1], (Sequence, Iterator))
        ):

Then I get '(False)(0)(0.0)()([])empty'.

I think in general inverted scopes have a lot of issues that aren't tested for some reason. Not sure yet.

I've got a commit that works. basically it passes an is_seq value into the render function when it's doing a sequence. Then when we're inside of a section or an inverted section I set that to false.

It works, but as you said, there's probably edge cases we're just not getting

Also I had to cleanup _get_key, as it was returning empty lists when they were referenced by {{.}}}, and not returning 0.0 when it was referenced by name (e.g. {{zerodotzero}} would output 0).

I could probably think of about 5 tests to add to ExpandedCoverage that this issue has unearthed. You found a good one @jrcutler 😛

@noahmorrison is this behavior correct? I'm pretty sure it's not.

    def test_array(self):
        args = {
            'template': '{{.}}',
            'data': ['b'],
        }

        result = chevron.render(**args)
        expected = '''['b']'''

        self.assertEqual(result, expected)

Yeah again the spec is pretty vague. Mustache.io prints 'b' so I guess when in doubt we should side with that?

If there was any sane way to fuzz this I'd be all for that.

@jrcutler there's definitely a fix coming! (Code is already done) But I'm gonna wait til the weekend to do anything as it's late and there's life stuff I have to go do.

Will there be a fix?