Skip to content

Commit c7d20c1

Browse files
committed
Make plugin list generator produce stable markdown
1 parent 30667f4 commit c7d20c1

2 files changed

Lines changed: 56 additions & 19 deletions

File tree

docs/source/plugin_list.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ Packages classified as inactive are excluded.
55

66
!!! warning
77

8-
Please be aware that this list is not a curated collection of projects and does not
9-
undergo a systematic review process. It serves purely as an informational resource to
10-
aid in the discovery of `pytask` plugins.
8+
```
9+
Please be aware that this list is not a curated collection of projects and does not
10+
undergo a systematic review process. It serves purely as an informational resource
11+
to aid in the discovery of `pytask` plugins.
1112
12-
Do not presume any endorsement from the `pytask` project or its developers, and always
13-
conduct your own quality assessment before incorporating any of these plugins into your
14-
own projects.
13+
Do not presume any endorsement from the `pytask` project or its developers, and
14+
always conduct your own quality assessment before incorporating any of these plugins
15+
into your own projects.
16+
```
1517

1618
This list contains 6 plugins.
1719

scripts/update_plugin_list.py

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737

3838
import httpx
3939
import packaging.version
40-
import tabulate
4140
import wcwidth
4241
from tqdm import tqdm
4342

@@ -46,18 +45,20 @@
4645

4746
_FILE_HEAD = """# Plugin List
4847
49-
PyPI projects that match `pytask-*` are considered plugins and are listed
50-
automatically. Packages classified as inactive are excluded.
48+
PyPI projects that match `pytask-*` are considered plugins and are listed automatically.
49+
Packages classified as inactive are excluded.
5150
5251
!!! warning
5352
54-
Please be aware that this list is not a curated collection of projects and does not
55-
undergo a systematic review process. It serves purely as an informational resource
56-
to aid in the discovery of `pytask` plugins.
53+
```
54+
Please be aware that this list is not a curated collection of projects and does not
55+
undergo a systematic review process. It serves purely as an informational resource
56+
to aid in the discovery of `pytask` plugins.
5757
58-
Do not presume any endorsement from the `pytask` project or its developers, and
59-
always conduct your own quality assessment before incorporating any of these plugins
60-
into your own projects.
58+
Do not presume any endorsement from the `pytask` project or its developers, and
59+
always conduct your own quality assessment before incorporating any of these plugins
60+
into your own projects.
61+
```
6162
6263
"""
6364

@@ -86,6 +87,43 @@ def _escape_markdown(text: str) -> str:
8687
return text.replace("|", "\\|")
8788

8889

90+
def _pad(text: str, width: int) -> str:
91+
"""Pad text to the requested display width."""
92+
return text + " " * (width - wcwidth.wcswidth(text))
93+
94+
95+
def _create_table(entries: list[dict[str, str]]) -> str:
96+
"""Create a markdown table in the repository's canonical format."""
97+
if not entries:
98+
msg = "Cannot create a plugin table without entries."
99+
raise ValueError(msg)
100+
101+
headers = list(entries[0])
102+
widths = [
103+
max(
104+
wcwidth.wcswidth(header),
105+
*(wcwidth.wcswidth(row[header]) for row in entries),
106+
)
107+
for header in headers
108+
]
109+
110+
header_cells = (
111+
_pad(header, width) for header, width in zip(headers, widths, strict=False)
112+
)
113+
header = "| " + " | ".join(header_cells) + " |"
114+
separator = "| " + " | ".join("-" * width for width in widths) + " |"
115+
rows = [
116+
"| "
117+
+ " | ".join(
118+
_pad(row[header], width)
119+
for header, width in zip(headers, widths, strict=False)
120+
)
121+
+ " |"
122+
for row in entries
123+
]
124+
return "\n".join([header, separator, *rows])
125+
126+
89127
def _iter_plugins() -> Generator[dict[str, str], None, None]: # noqa: C901
90128
"""Iterate over all plugins and format entries."""
91129
regex = r">([\d\w-]*)</a>"
@@ -168,10 +206,7 @@ def main() -> None:
168206
with plugin_list.open("w") as f:
169207
f.write(_FILE_HEAD)
170208
f.write(f"This list contains {len(plugins)} plugins.\n\n")
171-
172-
assert wcwidth # reference library that must exist for tabulate to work
173-
plugin_table = tabulate.tabulate(plugins, headers="keys", tablefmt="github")
174-
f.write(plugin_table)
209+
f.write(_create_table(plugins))
175210
f.write("\n")
176211

177212

0 commit comments

Comments
 (0)