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

feat: Support custom templates through objects' template attribute #70

Merged
merged 2 commits into from
May 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs/usage/extensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Extensions

## :warning: Work in Progress!

The Python handler supports extensions through
[*mkdocstrings*' handler extensions](https://mkdocstrings.github.io/usage/handlers/#handler-extensions).

Specifically, additional templates can be added to the handler,
and Griffe extensions can instruct the handler to use a particular template
for a particular object by setting a value in the Griffe object's `extra` dictionary:

```python title="griffe_extension.py"
obj = ... # get a reference to a Griffe object
if "mkdocstrings" not in obj.extra:
obj.extra["mkdocstrings"] = {}
obj.extra["mkdocstrings"]["template"] = "template_name.html"
```
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ nav:
- Sphinx: usage/docstrings/sphinx.md
- Advanced:
- Customization: usage/customization.md
- Extensions: usage/extensions.md
# defer to gen-files + literate-nav
- Code Reference: reference/
- Development:
Expand Down
4 changes: 3 additions & 1 deletion src/mkdocstrings_handlers/python/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,8 @@ def render(self, data: CollectorItem, config: Mapping[str, Any]) -> str: # noqa
mutabled_config = dict(copy.deepcopy(config))
final_config = ChainMap(mutabled_config, self.default_config)

template = self.env.get_template(f"{data.kind.value}.html")
template_name = rendering.do_get_template(data)
template = self.env.get_template(template_name)

# Heading level is a "state" variable, that will change at each step
# of the rendering recursion. Therefore, it's easier to use it as a plain value
Expand Down Expand Up @@ -335,6 +336,7 @@ def update_env(self, md: Markdown, config: dict) -> None: # noqa: D102 (ignore
self.env.filters["format_signature"] = rendering.do_format_signature
self.env.filters["filter_objects"] = rendering.do_filter_objects
self.env.filters["stash_crossref"] = lambda ref, length: ref
self.env.filters["get_template"] = rendering.do_get_template

def get_anchors(self, data: CollectorItem) -> set[str]: # noqa: D102 (ignore missing docstring)
try:
Expand Down
13 changes: 13 additions & 0 deletions src/mkdocstrings_handlers/python/rendering.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,16 @@ def formatter(code: str, line_length: int) -> str:
return format_str(code, mode=mode)

return formatter


def do_get_template(obj: Object) -> str:
"""Get the template name used to render an object.

Parameters:
obj: A Griffe object.

Returns:
A template name.
"""
extra_data = getattr(obj, "extra", {}).get("mkdocstrings", {})
return extra_data.get("template", "") or f"{obj.kind.value}.html"
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
{% with heading_level = heading_level + extra_level %}
{% for attribute in attributes|order_members(config.members_order, members_list) %}
{% if not attribute.is_alias or attribute.is_explicitely_exported %}
{% include "attribute.html" with context %}
{% include attribute|get_template with context %}
{% endif %}
{% endfor %}
{% endwith %}
Expand All @@ -42,7 +42,7 @@
{% with heading_level = heading_level + extra_level %}
{% for class in classes|order_members(config.members_order, members_list) %}
{% if not class.is_alias or class.is_explicitely_exported %}
{% include "class.html" with context %}
{% include class|get_template with context %}
{% endif %}
{% endfor %}
{% endwith %}
Expand All @@ -58,7 +58,7 @@
{% for function in functions|order_members(config.members_order, members_list) %}
{% if not (obj.kind.value == "class" and function.name == "__init__" and config.merge_init_into_class) %}
{% if not function.is_alias or function.is_explicitely_exported %}
{% include "function.html" with context %}
{% include function|get_template with context %}
{% endif %}
{% endif %}
{% endfor %}
Expand All @@ -75,7 +75,7 @@
{% with heading_level = heading_level + extra_level %}
{% for module in modules|order_members(config.members_order, members_list) %}
{% if not module.is_alias or module.is_explicitely_exported %}
{% include "module.html" with context %}
{% include module|get_template with context %}
{% endif %}
{% endfor %}
{% endwith %}
Expand All @@ -91,26 +91,26 @@
filter_objects(filters=config.filters, members_list=members_list, keep_no_docstrings=config.show_if_no_docstring)|
order_members(config.members_order, members_list) %}

{% if not (obj.kind.value == "class" and child.name == "__init__" and config.merge_init_into_class) %}
{% if not (obj.is_class and child.name == "__init__" and config.merge_init_into_class) %}

{% if child.kind.value == "attribute" %}
{% if child.is_attribute %}
{% with attribute = child %}
{% include "attribute.html" with context %}
{% include attribute|get_template with context %}
{% endwith %}

{% elif child.kind.value == "class" %}
{% elif child.is_class %}
{% with class = child %}
{% include "class.html" with context %}
{% include class|get_template with context %}
{% endwith %}

{% elif child.kind.value == "function" %}
{% elif child.is_function %}
{% with function = child %}
{% include "function.html" with context %}
{% include function|get_template with context %}
{% endwith %}

{% elif child.kind.value == "module" and config.show_submodules %}
{% elif child.is_module and config.show_submodules %}
{% with module = child %}
{% include "module.html" with context %}
{% include module|get_template with context %}
{% endwith %}

{% endif %}
Expand Down