pallets/jinja

Indent filter fails confusing if input is not string

alex-harvey-z3q opened this issue · 3 comments

Description

When calling the indent filter when the input is not a string (e.g. dict input), the filter fails with a confusing error message:

unsupported operand type(s) for +=: 'dict' and 'str'"

To reproduce

See the test I wrote:

    def test_indent_dict(self, env):
        self._test_indent_multiline_template(env)
        t = env.from_string('{{ mydict|indent }}')
        with pytest.raises(FilterArgumentError):
            t.render(mydict={"foo":"bar"})

Expected behaviour

An error message that advises that the filter has been called with unexpected inputs is expected.

Environment:

  • Python version: 3.10
  • Jinja version: latest

In general, Python does not do type checking just to show special error messages. If you pass in wrong data to something it might fail in weird ways at a weird spot. This filter isn't special in this regard.

@davidism If you look through the code, you have yourself already added a number of FilterArgumentExceptions—correctly, according to good design—to ensure that failures are graceful. Also, the idea that Python programmers normally don't bother to handle their exceptions and just let things blow up confusingly is .... not true.

Here's the standard library's own indent function, failing on invalid input without talking about str. Most other functions result in similar behavior. Convince the cpython maintainers that they should add runtime type checks for the arguments of each function they maintain, and I'll consider adding them all over the place in Jinja too.

>>> import textwrap
>>> textwrap.indent({}, "  ")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.10/textwrap.py", line 488, in indent
    return ''.join(prefixed_lines())
  File "/usr/local/lib/python3.10/textwrap.py", line 486, in prefixed_lines
    for line in text.splitlines(True):
AttributeError: 'dict' object has no attribute 'splitlines'