Skip to content

Commit 669b42e

Browse files
committed
feat: Release inheritance diagram features
1 parent 6d60023 commit 669b42e

File tree

7 files changed

+457
-0
lines changed

7 files changed

+457
-0
lines changed

docs/usage/configuration/general.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,143 @@ plugins:
269269

270270
WARNING: **Packages are loaded only once.** When mkdocstrings-python collects data from a Python package (thanks to [Griffe](https://mkdocstrings.github.io/griffe/)), it collects *the entire package* and *caches it*. Next time an object from the same package is rendered, the package is retrieved from the cache and not collected again. The `force_inspection` option will therefore only have an effect the first time a package is collected, and will do nothing for objects rendered afterwards.
271271

272+
[](){#option-inheritance_diagram_direction}
273+
## `inheritance_diagram_direction`
274+
275+
The direction of the Mermaid chart presenting the inheritance diagram of a class, `TD` by default.
276+
277+
```yaml title="mkdocs.yml"
278+
extra_javascript:
279+
- https://unpkg.com/mermaid@10.9.0/dist/mermaid.min.js
280+
```
281+
282+
```yaml title="in mkdocs.yml (global configuration)"
283+
plugins:
284+
- mkdocstrings:
285+
handlers:
286+
python:
287+
options:
288+
inheritance_diagram_direction: TD
289+
```
290+
291+
```md title="or in docs/some_page.md (local configuration)"
292+
::: path.to.object
293+
options:
294+
inheritance_diagram_direction: TD
295+
```
296+
297+
/// admonition | Preview
298+
type: preview
299+
300+
301+
With the following classes:
302+
303+
```python
304+
class SuperAbstract:
305+
"""Super abstract class."""
306+
class Mixin1:
307+
"""Mixin 1."""
308+
class Abstract(SuperAbstract, Mixin1):
309+
"""Abstract class."""
310+
class Mixin2A:
311+
"""Mixin 2A."""
312+
class Mixin2B(Mixin2A):
313+
"""Mixin 2B."""
314+
class Concrete(Abstract, Mixin2B):
315+
"""Concrete class."""
316+
class SuperConcrete(Concrete):
317+
"""Super concrete class."""
318+
```
319+
320+
//// tab | `TD` (or `TB`)
321+
322+
```mermaid
323+
flowchart TD
324+
SuperConcrete[SuperConcrete]
325+
Concrete[Concrete]
326+
Abstract[Abstract]
327+
SuperAbstract[SuperAbstract]
328+
Mixin1[Mixin1]
329+
Mixin2B[Mixin2B]
330+
Mixin2A[Mixin2A]
331+
332+
Concrete --> SuperConcrete
333+
Abstract --> Concrete
334+
SuperAbstract --> Abstract
335+
Mixin1 --> Abstract
336+
Mixin2B --> Concrete
337+
Mixin2A --> Mixin2B
338+
```
339+
340+
////
341+
342+
//// tab | `BT`
343+
344+
```mermaid
345+
flowchart BT
346+
SuperConcrete[SuperConcrete]
347+
Concrete[Concrete]
348+
Abstract[Abstract]
349+
SuperAbstract[SuperAbstract]
350+
Mixin1[Mixin1]
351+
Mixin2B[Mixin2B]
352+
Mixin2A[Mixin2A]
353+
354+
Concrete --> SuperConcrete
355+
Abstract --> Concrete
356+
SuperAbstract --> Abstract
357+
Mixin1 --> Abstract
358+
Mixin2B --> Concrete
359+
Mixin2A --> Mixin2B
360+
```
361+
362+
////
363+
364+
//// tab | `RL`
365+
366+
```mermaid
367+
flowchart RL
368+
SuperConcrete[SuperConcrete]
369+
Concrete[Concrete]
370+
Abstract[Abstract]
371+
SuperAbstract[SuperAbstract]
372+
Mixin1[Mixin1]
373+
Mixin2B[Mixin2B]
374+
Mixin2A[Mixin2A]
375+
376+
Concrete --> SuperConcrete
377+
Abstract --> Concrete
378+
SuperAbstract --> Abstract
379+
Mixin1 --> Abstract
380+
Mixin2B --> Concrete
381+
Mixin2A --> Mixin2B
382+
```
383+
384+
////
385+
386+
//// tab | `LR`
387+
388+
```mermaid
389+
flowchart LR
390+
SuperConcrete[SuperConcrete]
391+
Concrete[Concrete]
392+
Abstract[Abstract]
393+
SuperAbstract[SuperAbstract]
394+
Mixin1[Mixin1]
395+
Mixin2B[Mixin2B]
396+
Mixin2A[Mixin2A]
397+
398+
Concrete --> SuperConcrete
399+
Abstract --> Concrete
400+
SuperAbstract --> Abstract
401+
Mixin1 --> Abstract
402+
Mixin2B --> Concrete
403+
Mixin2A --> Mixin2B
404+
```
405+
406+
////
407+
///
408+
272409
[](){#option-preload_modules}
273410
## `preload_modules`
274411

src/mkdocstrings_handlers/python/_internal/config.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,14 @@ class PythonInputOptions:
560560
),
561561
] = 2
562562

563+
inheritance_diagram_direction: Annotated[
564+
Literal["TB", "TD", "BT", "RL", "LR"],
565+
_Field(
566+
group="docstrings",
567+
description="The direction of the Mermaid chart presenting the inheritance diagram of a class.",
568+
),
569+
] = "TD"
570+
563571
inherited_members: Annotated[
564572
bool | list[str],
565573
_Field(

src/mkdocstrings_handlers/python/templates/material/_base/class.html.jinja

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,54 @@ Context:
157157
{% endif %}
158158
{% endblock bases %}
159159

160+
{% block inheritance_diagram scoped %}
161+
{#- Inheritance diagram block.
162+
163+
This block renders the inheritance diagram for the class,
164+
using Mermaid syntax and a bit of JavaScript to make the nodes clickable,
165+
linking to the corresponding class documentation.
166+
-#}
167+
{% if config.show_inheritance_diagram and class.bases %}
168+
{% macro edges(class) %}
169+
{% for base in class.resolved_bases %}
170+
{{ base.path }} --> {{ class.path }}
171+
{{ edges(base) }}
172+
{% endfor %}
173+
{% endmacro %}
174+
<div style="display: none">
175+
<autoref identifier="{{ class.path }}" optional id="mermaid-link-{{ class.path }}"></autoref>
176+
{% for base in class.mro() %}
177+
<autoref identifier="{{ base.path }}" optional id="mermaid-link-{{ base.path }}"></autoref>
178+
{% endfor %}
179+
</div>
180+
<pre class="mermaid"><code id="mermaid-diagram-{{ class.path }}">
181+
flowchart {{ config.inheritance_diagram_direction }}
182+
{{ class.path }}[{{ class.name }}]
183+
{% for base in class.mro() %}
184+
{{ base.path }}[{{ base.name }}]
185+
{% endfor %}
186+
187+
{{ edges(class) | safe }}
188+
189+
click {{ class.path }} href "" "{{ class.path }}"
190+
{% for base in class.mro() %}
191+
click {{ base.path }} href "" "{{ base.path }}"
192+
{% endfor %}
193+
</code></pre>
194+
<script>
195+
var diagram = document.getElementById('mermaid-diagram-{{ class.path }}');
196+
diagram.innerHTML = diagram.innerHTML.replace(/click ([\w.]+) href "" "\1"/g, function(match, nodeID, offset) {
197+
try {
198+
const link = document.getElementById("mermaid-link-" + nodeID).href;
199+
return `click ${nodeID} href "${link}" "${nodeID}"`
200+
} catch (e) {
201+
return '';
202+
}
203+
});
204+
</script>
205+
{% endif %}
206+
{% endblock inheritance_diagram %}
207+
160208
{% block docstring scoped %}
161209
{#- Docstring block.
162210
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{% extends "_base/class.html.jinja" %}
2+
3+
{% block logs scoped %}
4+
{{ super() }}
5+
{# TODO: Switch to a warning after some time. #}
6+
{{ log.info(
7+
"DeprecationWarning: Extending '_base/class.html' is deprecated, extend '_base/class.html.jinja' instead. " ~
8+
"After some time, this message will be logged as a warning, causing strict builds to fail.",
9+
once=True,
10+
) }}
11+
{% endblock logs %}

0 commit comments

Comments
 (0)