Skip to content

Commit ddd8743

Browse files
authored
Merge pull request #247 from joe733/workshop
fix: generate dynamic reference docs
2 parents 8b46941 + 0a98524 commit ddd8743

File tree

4 files changed

+123
-35
lines changed

4 files changed

+123
-35
lines changed

.github/workflows/pages.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
- name: Build documentation
3838
run: |
3939
source .venv/bin/activate
40-
mkdocs build
40+
python ./docs/gen_docs.py
4141
- name: Setup Pages
4242
uses: actions/configure-pages@v3
4343
- name: Upload artifact

docs/gen_docs.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""Generate docs."""
2+
3+
# standard
4+
from shutil import copy, move, rmtree
5+
from yaml import safe_load, safe_dump
6+
from ast import parse, ImportFrom
7+
from typing import Dict, List
8+
from os.path import getsize
9+
from subprocess import run
10+
from pathlib import Path
11+
from sys import argv
12+
13+
14+
def _write_ref_content(source: Path, module_name: str, func_name: str):
15+
"""Write content."""
16+
with open(source, "at") as ref:
17+
ref.write(
18+
(f"# {module_name}\n\n" if getsize(source) == 0 else "")
19+
+ f"::: validators.{module_name}.{func_name}\n"
20+
)
21+
22+
23+
def generate_reference(source: Path, destination: Path):
24+
"""Generate reference."""
25+
nav_items: Dict[str, List[str]] = {"Code Reference": []}
26+
# clean destination
27+
if destination.exists() and destination.is_dir():
28+
rmtree(destination)
29+
destination.mkdir(exist_ok=True)
30+
# parse source
31+
v_ast = parse(source.read_text(), source)
32+
# generate reference content
33+
for namespace in (node for node in v_ast.body if isinstance(node, ImportFrom)):
34+
if not namespace.module:
35+
continue
36+
for alias in namespace.names:
37+
ref_module = destination / f"{namespace.module}.md"
38+
_write_ref_content(ref_module, namespace.module, alias.name)
39+
nav_items["Code Reference"].append(f"reference/{namespace.module}.md")
40+
return nav_items
41+
42+
43+
def update_mkdocs_config(source: Path, destination: Path, nav_items: Dict[str, List[str]]):
44+
"""Temporary update to mkdocs config."""
45+
copy(source, destination)
46+
with open(source, "rt") as mkf:
47+
mkdocs_conf = safe_load(mkf)
48+
mkdocs_conf["nav"] += [nav_items]
49+
with open(source, "wt") as mkf:
50+
safe_dump(mkdocs_conf, mkf, sort_keys=False)
51+
52+
53+
def generate_documentation(source: Path):
54+
"""Generate documentation."""
55+
# copy readme as docs index file
56+
copy(source / "README.md", source / "docs/index.md")
57+
# generate reference documentation
58+
nav_items = generate_reference(source / "validators/__init__.py", source / "docs/reference")
59+
# backup mkdocs config
60+
update_mkdocs_config(source / "mkdocs.yml", source / "mkdocs.bak.yml", nav_items)
61+
# build docs as subprocess
62+
print(run(("mkdocs", "build"), capture_output=True).stderr.decode())
63+
# restore mkdocs config
64+
move(source / "mkdocs.bak.yml", source / "mkdocs.yml")
65+
66+
67+
if __name__ == "__main__":
68+
project_dir = Path(__file__).parent.parent
69+
generate_documentation(project_dir)
70+
# use this option before building package
71+
# with `poetry build` to include refs
72+
if len(argv) > 1 and argv[1] == "--keep":
73+
quit()
74+
rmtree(project_dir / "docs/reference")

docs/index.md

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
1-
# Reference
2-
3-
::: validators.between
4-
5-
::: validators.btc_address
6-
7-
::: validators.card
8-
9-
::: validators.domain
10-
11-
::: validators.email
12-
13-
::: validators.hashes
14-
15-
::: validators.hostname
16-
17-
::: validators.iban
18-
19-
::: validators.ip_address
20-
21-
::: validators.length
22-
23-
::: validators.mac_address
24-
25-
::: validators.slug
26-
27-
::: validators.url
28-
29-
::: validators.uuid
30-
31-
---
32-
33-
::: validators.utils
1+
# validators - Python Data Validation for Humans™
2+
3+
[![Tests][tests-badge]][tests-link] [![Bandit][bandit-badge]][bandit-link] [![Version Status][vs-badge]][vs-link] [![Downloads][dw-badge]][dw-link]
4+
5+
Python has all kinds of data validation tools, but every one of them seems to
6+
require defining a schema or form. I wanted to create a simple validation
7+
library where validating a simple value does not require defining a form or a
8+
schema.
9+
10+
```python
11+
>>> import validators
12+
13+
>>> validators.email('[email protected]')
14+
True
15+
```
16+
17+
## Resources
18+
19+
- [Documentation](https://python-validators.github.io/)
20+
- [Issue Tracker](https://github.com/python-validators/validators/issues)
21+
- [Security](https://github.com/python-validators/validators/blob/master/SECURITY.md)
22+
- [Code](https://github.com/python-validators/validators/)
23+
24+
[//]: #(Links)
25+
26+
[bandit-badge]: https://github.com/python-validators/validators/actions/workflows/bandit.yml/badge.svg
27+
[bandit-link]: https://github.com/python-validators/validators/actions/workflows/bandit.yml
28+
[tests-badge]: https://github.com/python-validators/validators/actions/workflows/main.yml/badge.svg
29+
[tests-link]: https://github.com/python-validators/validators/actions/workflows/main.yml
30+
[vs-badge]: https://img.shields.io/pypi/v/validators.svg
31+
[vs-link]: https://pypi.python.org/pypi/validators/
32+
[dw-badge]: https://img.shields.io/pypi/dm/validators.svg
33+
[dw-link]: https://pypi.python.org/pypi/validators/

mkdocs.yml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,24 @@ watch: [README.md, validators/]
99

1010
nav:
1111
- Home: index.md
12-
- Code Reference: reference/
1312

1413
theme:
1514
name: material
15+
palette:
16+
- media: "(prefers-color-scheme: light)"
17+
scheme: default
18+
primary: white
19+
accent: teal
20+
toggle:
21+
icon: material/toggle-switch
22+
name: Switch to dark mode
23+
- media: "(prefers-color-scheme: dark)"
24+
scheme: slate
25+
primary: black
26+
accent: teal
27+
toggle:
28+
icon: material/toggle-switch-off-outline
29+
name: Switch to light mode
1630

1731
plugins:
1832
- search

0 commit comments

Comments
 (0)