New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improvement on filters #66
Conversation
The filter thing is pretty neat. What concerns me a bit is that it does not support arguments for the tests which might be a problem. For instance I will play a bit around with how it works and how it could be improved. |
Another thing is that i want to slowly deprecated 2.4 so that hack won't be necessary for 2.4. If 2.4 is detected just raise a runtime error if the key parameter is used. |
I have updated my |
By the way, I noticed an inconsistency on filters expecting iterables. Most filters leave the TypeError raised by the underlying built-in function (iter, reversed, list, sum, etc.), if the given value isn't an iterable, unhandled. But the In my opinion, all filters should deal with iterables in the same way. So in favor of less and simpler code, I would suggest to always let the underlying TypeError raise to the top instead of putting it into a FilterArgumentError, in the case of the |
I have got another question. Is it a bug or the intended behavior that the That way it seems some kind of inconsistent to me. But on the other hand if we would just do |
My latest commit made the |
Generally that looks all pretty good. For the filter i would also forward the kwargs to the test and only pop attribute if {{ foo|filter(test='my_test') }}
{{ foo|filter(test='my_test', these, are='args') }}
{{ foo|filter(attribute='my_test', _invert=true) }} The reason for prefixing The Regarding TypeError vs FilterArgumentError I think it would make sense to have a helper that asserts the type and otherwise raises the FilterArgumentError. Reasoning for that: if filters raise a FitlerArgumentError you can catch that down easily and do something else. This makes it possible to better try something and if it fails, attempt something else instead without hiding errors. |
Something else that I think would be cool to have is a map function that works like filter but does what python's map does and uses filters instead of tests: {% for username in users|map(attribute='username') %}
{{ username }}
{% endfor %}
{% for username in users|map(attribute='username')|map(filter='upper') %}
{{ username }}
{% endfor %} etc. |
I don't like the idea of adding an underscore as prefix to the How do you mean that a FilterArgumentError can be catched in order to try something else, in a way that you can't do with a TypeError? However preemptive type or constraint checks are anything but pythonic. Have a look at the I already thought, about adding a {{ foo|map(attribute='bar')|join(',') }}
{{ foo|map(attribute='bar')|sum }} Do you agree on that and if so how should we deprecate it? Of course we could just call |
I don't like deprecating things in the template language aspect of Jinja2. There is not much value in that. Also the way that join and sum work is that they don't have to buffer up things if they take the attribute directly and it's more expressive. I don't mind having more than one way to do things in the template aspect of things if this means that I don't break backwards compat. Regarding the FitlerArgumentError the usecase is that if you know that an invalid argument to the filter raises that exception instead of type error you can catch down an invalid invocation separately from something inside the filter breaking because of a bug in the filter. Especially in combination with the sandboxed execution that is a nice feature to have. |
Instead of the invert I would add a |
Sorry, for accidentally closing the pull request. You might also have a look at Pull Request #57. It suggests using getattr() instead of getitem() in make_attrgetter(), which absolutely makes sense, in my opinion. There is also Pull Request #42, which I recommend to reject in favor of the |
…func into a factory function.
…d 'dictsort' filter.
* Keyword arguments are passed in addition to positional arguments to the test function, now. * The 'invert' keyword argument was removed in favor of a new filter called 'filterfalse'. * The new filter 'map' was added. It shares most of its code with the 'filter' and 'filterfalse' filters, but expects a filter instead of test and calls map() instead of filter().
…t.getattr. That way we don't need to repeat the logic in the `attr` filter. Also it simplifies the implementation of the derived SandboxedEnvironment.
filters. This supercedes #66
A small version of this is now implemented in a different form. |
Sorry for posting on an old issue, but why did you not add the |
I have added the template filters, listed below and have done some improvements on existing filters.
You find further details including examples in the docstring of those filter functions.