Skip to content

Commit 2f2ddfc

Browse files
authored
Merge pull request #259 from Guzz-T/issue/189/gen-docs
Add a workflow that auto-generate the luxtronik field definition documentation
2 parents db38809 + 56c8603 commit 2f2ddfc

15 files changed

Lines changed: 25433 additions & 1 deletion

File tree

.github/workflows/docs.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Generate and deploy docs to GH pages
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
concurrency:
14+
group: "pages"
15+
cancel-in-progress: false
16+
17+
jobs:
18+
deploy:
19+
environment:
20+
name: github-pages
21+
url: ${{ steps.deployment.outputs.page_url }}
22+
runs-on: ubuntu-latest
23+
steps:
24+
- name: Checkout
25+
uses: actions/checkout@v6
26+
- name: Install uv
27+
uses: astral-sh/setup-uv@v7
28+
- name: Set up Python
29+
run: uv python install
30+
- name: Install dependencies
31+
run: |
32+
uv venv
33+
uv pip install jinja2
34+
uv pip install -e .
35+
- name: Generate docs
36+
run: uv run python .github/workflows/scripts/docs/gen-docs.py
37+
- name: Setup Pages
38+
uses: actions/configure-pages@v5
39+
- name: Upload artifact
40+
uses: actions/upload-pages-artifact@v4
41+
with:
42+
path: docs
43+
- name: Deploy to GitHub Pages
44+
id: deployment
45+
uses: actions/deploy-pages@v4
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/usr/bin/env python
2+
import logging
3+
from pathlib import Path
4+
from datetime import datetime
5+
from jinja2 import Environment, FileSystemLoader, select_autoescape
6+
import subprocess
7+
8+
from luxtronik.cfi import (
9+
CALCULATIONS_DEFINITIONS,
10+
PARAMETERS_DEFINITIONS,
11+
VISIBILITIES_DEFINITIONS,
12+
)
13+
from luxtronik.shi import (
14+
INPUTS_DEFINITIONS,
15+
HOLDINGS_DEFINITIONS,
16+
)
17+
18+
from luxtronik.datatypes import (
19+
SelectionBase,
20+
)
21+
22+
logging.basicConfig(level=logging.INFO)
23+
logger = logging.getLogger("docs generator")
24+
25+
26+
BASEPATH = Path(__file__).resolve().parent
27+
28+
29+
def get_git_version():
30+
try:
31+
return subprocess.check_output(
32+
["git", "describe", "--tags"],
33+
stderr=subprocess.STDOUT
34+
).decode().strip()
35+
except Exception:
36+
return None
37+
38+
def get_string(string):
39+
return f'"{str(string)}"'
40+
41+
def get_writeable(writeable):
42+
return get_string("y" if writeable else "")
43+
44+
def get_unit(unit):
45+
return get_string(unit if unit else "")
46+
47+
def get_version(version):
48+
return get_string("" if version is None else ".".join(map(str, version[:3])))
49+
50+
def get_desc(desc):
51+
return get_string(desc.replace('\n', '\\n'))
52+
53+
def get_items(definitions):
54+
items = []
55+
for d in definitions:
56+
desc = d.description
57+
if issubclass(d.field_type, SelectionBase) and d.writeable:
58+
desc += ("\n" if desc else "") + "\nUser-Options:\n" + "\n".join(d.field_type.options())
59+
for n in d.names:
60+
items.append({
61+
"category": get_string(definitions.name),
62+
"index": d.index,
63+
"name": get_string(n),
64+
"lsb": 0 if d.bit_offset is None else d.bit_offset,
65+
"width": d.num_bits,
66+
"class": get_string(d.field_type.datatype_class),
67+
"writeable": get_writeable(d.writeable),
68+
"unit": get_unit(d.field_type.unit),
69+
"since": get_version(d.since),
70+
"until": get_version(d.until),
71+
"description": get_desc(desc),
72+
})
73+
return items
74+
75+
def gather_data():
76+
logger.info("gather docs data")
77+
defs = [
78+
PARAMETERS_DEFINITIONS,
79+
CALCULATIONS_DEFINITIONS,
80+
VISIBILITIES_DEFINITIONS,
81+
HOLDINGS_DEFINITIONS,
82+
INPUTS_DEFINITIONS
83+
]
84+
data = {}
85+
for d in defs:
86+
data[d.name] = get_items(d)
87+
return data
88+
89+
def render_docs():
90+
logger.info("render docs")
91+
env = Environment(loader=FileSystemLoader(str(BASEPATH / "templates")), autoescape=select_autoescape())
92+
93+
data = gather_data()
94+
(BASEPATH.parents[3] / "docs").mkdir(exist_ok=True)
95+
96+
# create data files
97+
template = env.get_template("definitions.js")
98+
for name, items in data.items():
99+
with open(BASEPATH.parents[3] / f"docs/{name}.js", "w", encoding="UTF-8") as f:
100+
f.write(template.render(group=name.upper(), data=items))
101+
102+
# create meta file
103+
template = env.get_template("meta.js")
104+
with open(BASEPATH.parents[3] / "docs/meta.js", "w", encoding="UTF-8") as f:
105+
f.write(template.render(version=get_git_version(), now=datetime.now().replace(microsecond=0)))
106+
107+
108+
if __name__ == "__main__":
109+
render_docs()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
window.{{ group }} = [
2+
{% for items in data %}{{"{"}}{% for key, value in items.items() %}
3+
{{key}}: {{value}}{% if not loop.last %},{% endif %}{% endfor %}
4+
{{"}"}}{% if not loop.last %},{% endif %}{% endfor %}
5+
];
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
window.META = {
2+
createdOn: "{{ now }}",
3+
version: "{{ version }}"
4+
};

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This changelog follows the "Keep a Changelog" format and Semantic Versioning.
1515
is required for this. See README for further information. [#190]
1616
- Add a command-line-interface (CLI) with the following commands:
1717
`dump`, `dump-cfi`, `dump.shi`, `changes`, `watch-cfi`, `watch-shi`, `discover`
18+
- Provide an automatically generated documentation for the data fields. [#189]
1819

1920
### Changed
2021

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ There is no automatically rendered documentation of this library available yet,
5656
so you'll have to fall back to using the source code itself as documentation.
5757
It can be found in the [luxtronik](luxtronik/) directory.
5858

59-
Discovered data fields:
59+
At least for the data fields, there is such a
60+
[documentation](https://bouni.github.io/python-luxtronik/). Alternatively,
61+
you can take a look at the definitions for all discovered data fields:
6062

6163
- Calculations holds measurement values (config interface): \
6264
[luxtronik/definitions/calculations.py](luxtronik/definitions/calculations.py)

0 commit comments

Comments
 (0)