Skip to content

Commit 834893a

Browse files
authored
Add some useful mkdocs extensions (#244)
We also make some initial use of them, but this is also in preparation of the creation of the user guide. - Add the `mkdocs-include-markdown-plugin` - Add the `markdown-svgbob` extension - Render `Timer` diagrams with svgbob - Reuse parts of `README.md` in `docs/index.md`
2 parents 8e624b4 + d6b2275 commit 834893a

File tree

6 files changed

+102
-32
lines changed

6 files changed

+102
-32
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
## Introduction
88

9+
<!-- introduction -->
10+
911
Frequenz Channels is a *channels* implementation for Python.
1012

1113
According to [Wikipedia](https://en.wikipedia.org/wiki/Channel_(programming)):
@@ -20,14 +22,20 @@ Frequenz Channels are mostly designed after [Go
2022
channels](https://tour.golang.org/concurrency/2) but it also borrows ideas from
2123
[Rust channels](https://doc.rust-lang.org/book/ch16-02-message-passing.html).
2224

25+
<!-- /introduction -->
26+
2327
## Supported Platforms
2428

29+
<!-- supported-platforms -->
30+
2531
The following platforms are officially supported (tested):
2632

2733
- **Python:** 3.11
2834
- **Operating System:** Ubuntu Linux 20.04
2935
- **Architectures:** amd64, arm64
3036

37+
<!-- /supported-platforms -->
38+
3139
## Quick Start
3240

3341
We assume you are on a system with Python available. If that is not the case,

docs/_scripts/macros.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
from typing import Any
77

88
import markdown as md
9+
from griffe import Object
10+
from griffe.collections import ModulesCollection
911
from markdown.extensions import toc
1012
from mkdocs_macros import plugin as macros
13+
from mkdocstrings_handlers.python.handler import PythonHandler
1114

1215
_CODE_ANNOTATION_MARKER: str = (
1316
r'<span class="md-annotation">'
@@ -77,5 +80,41 @@ def define_env(env: macros.MacrosPlugin) -> None:
7780
# https://squidfunk.github.io/mkdocs-material/reference/code-blocks/#adding-annotations
7881
env.variables["code_annotation_marker"] = _CODE_ANNOTATION_MARKER
7982

83+
python_handler = env.conf["plugins"]["mkdocstrings"].get_handler("python")
84+
assert isinstance(python_handler, PythonHandler)
85+
86+
def _get_docstring(symbol: str) -> str:
87+
symbols = python_handler._modules_collection # pylint: disable=protected-access
88+
assert isinstance(symbols, ModulesCollection)
89+
90+
try:
91+
obj = symbols[symbol]
92+
except KeyError as exc:
93+
raise ValueError(f"Symbol {symbol!r} not found.") from exc
94+
assert isinstance(obj, Object)
95+
96+
docstring = obj.docstring
97+
if not docstring:
98+
raise ValueError(f"Symbol {symbol!r} has no docstring.")
99+
100+
return docstring.value
101+
102+
# The decorator makes the function untyped
103+
@env.macro # type: ignore[misc]
104+
def docstring_summary(symbol: str) -> str:
105+
"""Get the summary of a Python symbol.
106+
107+
Args:
108+
symbol: The fully qualified name of the Python symbol to get the summary of.
109+
110+
Returns:
111+
The summary of the Python symbol.
112+
"""
113+
docstring = _get_docstring(symbol)
114+
summary = docstring.splitlines(keepends=False)[0]
115+
return python_handler.do_convert_markdown(
116+
summary, heading_level=1, strip_paragraph=True
117+
)
118+
80119
# This hook needs to be done at the end of the `define_env` function.
81120
_hook_macros_plugin(env)

docs/index.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
## Introduction
44

5-
Frequenz Channels is a *channels* implementation for Python.
5+
{%
6+
include-markdown "../README.md"
7+
start="<!-- introduction -->"
8+
end="<!-- /introduction -->"
9+
%}
610

7-
According to [Wikipedia](https://en.wikipedia.org/wiki/Channel_(programming)):
11+
## Supported Platforms
812

9-
> A channel is a model for interprocess communication and synchronization via
10-
> message passing. A message may be sent over a channel, and another process or
11-
> thread is able to receive messages sent over a channel it has a reference to,
12-
> as a stream. Different implementations of channels may be buffered or not,
13-
> and either synchronous or asynchronous.
14-
15-
Frequenz Channels are mostly designed after [Go
16-
channels](https://tour.golang.org/concurrency/2) but it also borrows ideas from
17-
[Rust channels](https://doc.rust-lang.org/book/ch16-02-message-passing.html).
13+
{%
14+
include-markdown "../README.md"
15+
start="<!-- supported-platforms -->"
16+
end="<!-- /supported-platforms -->"
17+
%}
1818

1919
## Installation
2020

@@ -77,5 +77,5 @@ $ python3
7777
Python 3.11.4 (main, Jun 7 2023, 10:13:09) [GCC 12.2.0] on linux
7878
Type "help", "copyright", "credits" or "license" for more information.
7979
>>> import frequenz.channels
80-
>>>
80+
>>>
8181
```

mkdocs.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ theme:
2424
features:
2525
- content.code.annotate
2626
- content.code.copy
27+
- navigation.expand
28+
- navigation.footer
2729
- navigation.indexes
2830
- navigation.instant
29-
- navigation.footer
3031
- navigation.tabs
3132
- navigation.top
3233
- navigation.tracking
@@ -67,6 +68,8 @@ markdown_extensions:
6768
- attr_list
6869
- def_list
6970
- footnotes
71+
- markdown_svgbob:
72+
min_char_width: 0
7073
- pymdownx.details
7174
- pymdownx.highlight:
7275
anchor_linenums: true
@@ -90,6 +93,7 @@ plugins:
9093
- gen-files:
9194
scripts:
9295
- docs/_scripts/mkdocstrings_autoapi.py
96+
- include-markdown
9397
- literate-nav:
9498
nav_file: SUMMARY.md
9599
- mike:
@@ -129,3 +133,4 @@ plugins:
129133
watch:
130134
- "src"
131135
- CONTRIBUTING.md
136+
- README.md

pyproject.toml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,33 +45,35 @@ dev-flake8 = [
4545
]
4646
dev-formatting = ["black == 23.10.1", "isort == 5.12.0"]
4747
dev-mkdocs = [
48+
"Markdown == 3.5.1",
4849
"black == 23.10.1",
49-
"Markdown==3.5.1",
50+
"frequenz-repo-config[lib] == 0.7.5",
51+
"markdown-svgbob == 202112.1022",
5052
"mike == 2.0.0",
5153
"mkdocs-gen-files == 0.5.0",
54+
"mkdocs-include-markdown-plugin == 6.0.4",
5255
"mkdocs-literate-nav == 0.6.1",
53-
"mkdocs-material == 9.4.7",
5456
"mkdocs-macros-plugin == 1.0.5",
57+
"mkdocs-material == 9.4.7",
5558
"mkdocstrings[python] == 0.23.0",
56-
"frequenz-repo-config[lib] == 0.7.5",
5759
]
5860
dev-mypy = [
59-
"mypy == 1.6.1",
60-
"types-Markdown == 3.5.0.0",
6161
# For checking the noxfile, docs/ script, and tests
6262
"frequenz-channels[dev-mkdocs,dev-noxfile,dev-pytest]",
63+
"mypy == 1.6.1",
64+
"types-Markdown == 3.5.0.0",
6365
]
6466
dev-noxfile = ["nox == 2023.4.22", "frequenz-repo-config[lib] == 0.7.5"]
6567
dev-pylint = [
66-
"pylint == 3.0.2",
6768
# For checking the noxfile, docs/ script, and tests
6869
"frequenz-channels[dev-mkdocs,dev-noxfile,dev-pytest]",
70+
"pylint == 3.0.2",
6971
]
7072
dev-pytest = [
71-
"pytest == 7.4.3",
7273
"async-solipsism == 0.5",
73-
"hypothesis == 6.88.1",
7474
"frequenz-repo-config[extra-lint-examples] == 0.7.5",
75+
"hypothesis == 6.88.1",
76+
"pytest == 7.4.3",
7577
"pytest-asyncio == 0.21.1",
7678
"pytest-mock == 3.12.0",
7779
]

src/frequenz/channels/timer.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,16 @@ class TriggerAllMissed(MissedTickPolicy):
8787
`T5`, happens at 5.1 (0.1 seconds late), so it triggers immediately
8888
again. The seventh tick, `T6`, happens at 6.0, right on time.
8989
90-
```
91-
0 1 2 3 4 o 5 6
92-
o---------|-o-------|--o------|---------|--o------|o--------o-----> time
90+
<center>
91+
```bob
92+
0 1 2 3 4 T4 5 6
93+
*---------o-*-------o--*------o---------o--**-----o*--------*-----> time
9394
T0 T1 T2 T3 T5 T6
94-
T4
95+
96+
-o- "Expected ticks"
97+
-*- "Delivered ticks"
9598
```
99+
</center>
96100
"""
97101

98102
def calculate_next_tick_time(
@@ -134,11 +138,17 @@ class SkipMissedAndResync(MissedTickPolicy):
134138
`T5`, happens at 5.1 (0.1 seconds late), so it triggers immediately
135139
again. The seventh tick, `T6`, happens at 6.0, right on time.
136140
141+
<center>
142+
```bob
143+
0 1 2 3 4 T4 5 6
144+
*---------o-*-------o--*------o---------o--*O-----o-*-------*-----> time
145+
T0 T1 T2 T3 T5 T6
146+
147+
-o- "Expected ticks"
148+
-*- "Delivered ticks"
149+
-O- "Undelivered ticks (skipped)"
137150
```
138-
0 1 2 3 4 o 5 6
139-
o---------|-o-------|--o------|---------|--o------|o--------o-----> time
140-
T0 T1 T2 T3 T5 T6
141-
```
151+
</center>
142152
"""
143153

144154
def calculate_next_tick_time(
@@ -187,11 +197,17 @@ class SkipMissedAndDrift(MissedTickPolicy):
187197
so is right on time (no drift) and the same happens for tick `T6.3`,
188198
which triggers at 6.3 seconds.
189199
190-
```
200+
<center>
201+
```bob
191202
0 1 2 3 4 5 6
192-
o---------|-o-------|--o------|---------|--o------|--o------|--o--> time
193-
T0 T1 T2.2 T3.2 T5.3 T6.3
203+
*---------o-*-------|-o*------|-O-------|-o*------|--*------|--*--> time
204+
T0 T1.2 T2.2 T3.2 T4.2 T5.3 T6.3
205+
206+
-o- "Expected ticks"
207+
-*- "Delivered ticks"
208+
-O- "Undelivered ticks (skipped)"
194209
```
210+
</center>
195211
"""
196212

197213
def __init__(self, *, delay_tolerance: timedelta = timedelta(0)):

0 commit comments

Comments
 (0)