Skip to content
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

Custom Filter for Jinja Renderer #9

Open
suhendiandigo opened this issue Jan 26, 2022 · 3 comments
Open

Custom Filter for Jinja Renderer #9

suhendiandigo opened this issue Jan 26, 2022 · 3 comments
Labels
enhancement New feature or request

Comments

@suhendiandigo
Copy link

Hello @radeklat , thanks for the last update to expose classes. So far, I am enjoying my experience in auto generating configurations for my apps :D.

Currently I am contemplating the solution for one of my use cases. I want to display the class title and render each classes sorted by their titles. I displayed the title by using the following macro:

{% macro class_title(class) -%}
{% if class.Config|attr('title') -%}
{{ class.Config.title }}
{%- else -%}
{{ class.__name__ }}
{%- endif %}
{%- endmacro %}

However, I reached a conundrum while trying to sort the classes by their title. After some tinkering, I figured out a way to achieve this is to add custom filters. So I modified the main.py (for testing purpose):

class_title = env.globals["class_title"] = lambda x: x.Config.title if hasattr(getattr(x, 'Config', None), 'title') else x.__name__
env.filters["sort_title"] = lambda x: list(sorted(x, key=class_title))

And I use them in the following way:

{% for class in classes|sort_title %}
{{ heading(2) }} {{ class_title(class) }}
{% endfor %}

I am wondering what are your thoughts on this and if it is worth supporting custom filters without having to modify the main.py. I will gladly write a pull request if you think that this is a good idea/feature to support.

@radeklat
Copy link
Owner

Hi Suhendi. Custom filters certainly make sense, even outside of this use case. It could be perhaps implemented as new command line option, pointing to a Python file that contains custom filter functions? And use the function names as the filter names.

For example:

settings-doc ... --jinja-filters filters.py

where filters.py could look like:

from typing import Type, List, Iterable

def class_title(cls: Type) -> str:
	return cls.Config.title if hasattr(getattr(cls, 'Config', None), 'title') else cls.__name__

def sort_title(iterable: Iterable) -> List:
	return list(sorted(iterable, key=class_title))

@suhendiandigo
Copy link
Author

suhendiandigo commented Jan 28, 2022

Thanks for your feedback. I will get started with a draft of sort.

On the topic of expanding the jinja functionality, I am thinking that maybe we can instead create some sort of hooks that passes the jinja Environment to be modified freely.

Something along the line of the following:
settings-doc ... --hooks settings_doc_hooks.py

where settings_doc_hooks.py could contain the hook (if not multiple hooks):

from typing import Type, List, Iterable
from jinja2 import Environment

def class_title(cls: Type) -> str:
    return cls.Config.title if hasattr(getattr(cls, 'Config', None), 'title') else cls.__name__

def sort_title(iterable: Iterable) -> List:
    return list(sorted(iterable, key=class_title))

def settings_doc_initialize_environment(env: Environment) -> None:
    env.globals["class_title"] = class_title
    env.filters["sort_title"] = sort_title

This way we can extend some of the functionality such as creating a hook for preprocessing the classes: List[Type[BaseSettings]] before passing it to the renderer

@radeklat
Copy link
Owner

radeklat commented Jan 28, 2022

That's also a good idea 👍 It is likely more attributes of the Environment will need customization. So why not to expose it entirely.

@radeklat radeklat added the enhancement New feature or request label Jan 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants