{%- macro print_opts(options, indent=' ', count=0) %}{% for key in options.keys() | sort2 %} {% set value = options[key] %} {% if value is string %} {{- indent*count }}{{ key }} {{ '"' + value.split('\t') | join('" "') + '"' }} {% elif value in [true, false] %} {{- indent*count }}{{ key }} {{ value | lower }} {% elif value is number %} {{- indent*count }}{{ key }} {{ value }} {% elif value is mapping %} {{- indent*count }}<{{ key }}> {{ print_opts(value, indent, count+1) -}} {{- indent*count }}</{{ key.split()[0] }}> {% elif value is sequence %} {% for i in value | sort2 -%} {{ print_opts({key: i}, indent, count) -}} {%- endfor %} {% else %} {{- indent*count }}{{ key }} "{{ value }}" {% endif %}{% endfor %}{% endmacro %}
from jinja2._compat import string_typesfrom operator import itemgetter
def environmentfilter(f): """Decorator for marking environment dependent filters. The current :class:`Environment` is passed to the filter as first argument. """ f.environmentfilter = True return f
@environmentfilterdef do_sort(environment, value, reverse=False, case_sensitive=False, attribute=None):
if not case_sensitive: def sort_func(item): if isinstance(item, string_types): item = item.lower() return item else: sort_func = None
if attribute is not None: getter = make_attrgetter(environment, attribute) def sort_func(item, processor=sort_func or (lambda x: x)): return processor(getter(item))
print(type(value)) if isinstance(value, list) and isinstance(value[0], dict): return sorted(value, key=lambda x:sorted(x.keys()), reverse=reverse) else: return sorted(value, key=sort_func, reverse=reverse)
class FilterModule(object): ''' custom jinja2 sort filter '''
def filters(self): return { 'sort2': do_sort }