From 99f9a15b367d5c7e3746ef2a4feebc1e09dc5597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Wed, 16 Aug 2023 15:33:12 +0200 Subject: [PATCH] feat: Support new Griffe expressions (in v0.33) --- pyproject.toml | 2 +- src/mkdocstrings_handlers/python/handler.py | 1 + src/mkdocstrings_handlers/python/rendering.py | 22 +++++++ .../templates/material/_base/expression.html | 58 ++++++++++++++----- 4 files changed, 69 insertions(+), 14 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 04f1b273..c25588d5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ classifiers = [ ] dependencies = [ "mkdocstrings>=0.20", - "griffe>=0.30,<0.33", + "griffe>=0.33", ] [project.urls] diff --git a/src/mkdocstrings_handlers/python/handler.py b/src/mkdocstrings_handlers/python/handler.py index 7a7d0da3..bd25424d 100644 --- a/src/mkdocstrings_handlers/python/handler.py +++ b/src/mkdocstrings_handlers/python/handler.py @@ -340,6 +340,7 @@ def update_env(self, md: Markdown, config: dict) -> None: # noqa: D102 (ignore self.env.trim_blocks = True self.env.lstrip_blocks = True self.env.keep_trailing_newline = False + self.env.filters["split_path"] = rendering.do_split_path self.env.filters["crossref"] = rendering.do_crossref self.env.filters["multi_crossref"] = rendering.do_multi_crossref self.env.filters["order_members"] = rendering.do_order_members diff --git a/src/mkdocstrings_handlers/python/rendering.py b/src/mkdocstrings_handlers/python/rendering.py index ce6cf9cb..7a875a5c 100644 --- a/src/mkdocstrings_handlers/python/rendering.py +++ b/src/mkdocstrings_handlers/python/rendering.py @@ -174,6 +174,28 @@ def repl(match: Match) -> str: return Markup(text).format(**variables) +def do_split_path(path: str, full_path: str) -> list[tuple[str, str]]: + """Split object paths for building cross-references. + + Parameters: + path: The path to split. + + Returns: + A list of pairs (title, full path). + """ + if "." not in path: + return [(path, full_path)] + pairs = [] + full_path = "" + for part in path.split("."): + if full_path: + full_path += f".{part}" + else: + full_path = part + pairs.append((part, full_path)) + return pairs + + def _keep_object(name: str, filters: Sequence[tuple[Pattern, bool]]) -> bool: keep = None rules = set() diff --git a/src/mkdocstrings_handlers/python/templates/material/_base/expression.html b/src/mkdocstrings_handlers/python/templates/material/_base/expression.html index 9bcfc867..52d3a624 100644 --- a/src/mkdocstrings_handlers/python/templates/material/_base/expression.html +++ b/src/mkdocstrings_handlers/python/templates/material/_base/expression.html @@ -1,14 +1,46 @@ -{%- set original_expression = expression -%} -{%- if original_expression is iterable and original_expression is not string -%} - {%- for expression in original_expression -%} - {%- include "expression.html" with context -%} - {%- endfor -%} -{%- elif original_expression is string -%} - {{ original_expression }} -{%- else -%} - {%- with annotation = original_expression|attr(config.annotations_path) -%} - {%- filter stash_crossref(length=annotation|length) -%} - {{ annotation }} - {%- endfilter -%} +{%- macro crossref(name, annotation_path) -%} + {%- with full = name.canonical_path -%} + {%- if annotation_path == "brief" -%} + {%- set annotation = name.canonical_name -%} + {%- elif annotation_path == "source" -%} + {%- set annotation = name.name -%} + {%- elif annotation_path == "full" -%} + {%- set annotation = full -%} + {%- endif -%} + {%- for title, path in annotation|split_path(full) -%} + {%- filter stash_crossref(length=title|length) -%} + {{ title }} + {%- endfilter -%} + {%- if not loop.last -%}.{%- endif -%} + {%- endfor -%} {%- endwith -%} -{%- endif -%} +{%- endmacro -%} + +{%- macro render(expression, annotations_path) -%} + {%- if expression is string -%} + {%- if signature -%}{{ expression|safe }}{%- else -%}{{ expression }}{%- endif -%} + {%- elif expression.classname == "ExprName" -%} + {{ crossref(expression, annotations_path) }} + {%- elif expression.classname == "ExprAttribute" -%} + {%- if annotations_path == "brief" -%} + {{ render(expression.last, "brief") }} + {%- elif annotations_path == "full" -%} + {{ render(expression.first, "full") }} + {%- for element in expression -%} + {%- if not loop.first -%} + {{ render(element, "brief") }} + {%- endif -%} + {%- endfor -%} + {%- else -%} + {%- for element in expression -%} + {{ render(element, annotations_path) }} + {%- endfor -%} + {%- endif -%} + {%- else -%} + {%- for element in expression -%} + {{ render(element, annotations_path) }} + {%- endfor -%} + {%- endif -%} +{%- endmacro -%} + +{{ render(expression, config.annotations_path) }}