File: generate_files.py

package info (click to toggle)
python-sphinx-chango 0.5.0-2
  • links: PTS
  • area: main
  • in suites: sid
  • size: 1,776 kB
  • sloc: python: 4,909; javascript: 74; makefile: 23
file content (111 lines) | stat: -rw-r--r-- 2,710 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#  SPDX-FileCopyrightText: 2024-present Hinrich Mahler <chango@mahlerhome.de>
#
#  SPDX-License-Identifier: MIT
import importlib
import logging
from pathlib import Path
from types import ModuleType

from jinja2 import Template

logger = logging.getLogger(__name__)


CLASS_TEMPLATE = Template(
    """{{ class_name }}
{{ "=" * class_name|length }}

.. autoclass:: {{ fqn }}
    :members:
    :show-inheritance:
"""
)

MODULE_TEMPLATE = Template(
    """{{ module_name }}
{{ "=" * module_name|length }}

.. automodule:: {{ fqn }}

.. toctree::
    :titlesonly:

    {% for child in children -%}
    {{ child }}
    {% endfor -%}
"""
)


def write_text(file_path: Path, content: str) -> None:
    if file_path.exists():
        logger.debug("File %s already exists, skipping", file_path)
        return
    file_path.write_text(content, encoding="utf-8")


def write_class_rst_file(class_name: str, fqn: str, output_dir: Path) -> Path:
    file_name = f"{fqn.lower()}.rst"
    file_path = output_dir / file_name
    write_text(file_path, CLASS_TEMPLATE.render(class_name=class_name, fqn=fqn))

    return file_path


def write_module_rst_file(
    module_name: str, fqn: str, children: list[Path], output_dir: Path
) -> Path:
    file_name = f"{fqn.lower()}.rst"
    file_path = output_dir / file_name
    write_text(
        file_path,
        MODULE_TEMPLATE.render(
            module_name=module_name, fqn=fqn, children=sorted(child.stem for child in children)
        ),
    )

    return file_path


def create_rst_files(module_name: str, base_path: Path) -> list[Path]:
    try:
        module = importlib.import_module(module_name)
    except ImportError:
        logger.error("Could not import module %s", module_name)
        return []

    if not hasattr(module, "__all__"):
        return []

    created_files: list[Path] = []

    for name in module.__all__:
        fqn = f"{module_name}.{name}"
        try:
            member = getattr(module, name)
        except AttributeError:
            continue

        if not isinstance(member, type | ModuleType):
            # Rest is covered on module level
            continue

        if isinstance(member, type):
            created_files.append(write_class_rst_file(name, fqn, base_path))
        else:
            sub_files = create_rst_files(fqn, base_path)
            created_files.append(write_module_rst_file(name, fqn, sub_files, base_path))

    write_module_rst_file(module_name, module_name, created_files, base_path)
    return created_files


def main() -> None:
    output_dir = Path(__file__).parent / "source"
    output_dir.mkdir(exist_ok=True)

    create_rst_files("chango", output_dir)


if __name__ == "__main__":
    main()