File: _macros.py

package info (click to toggle)
superqt 0.7.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,320 kB
  • sloc: python: 9,108; makefile: 16; sh: 12
file content (136 lines) | stat: -rw-r--r-- 3,982 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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import sys
from enum import EnumMeta
from importlib import import_module
from pathlib import Path
from textwrap import dedent
from typing import TYPE_CHECKING

from jinja2 import pass_context
from qtpy.QtCore import QObject, Signal

if TYPE_CHECKING:
    from mkdocs_macros.plugin import MacrosPlugin

EXAMPLES = Path(__file__).parent.parent / "examples"
IMAGES = Path(__file__).parent / "_auto_images"
IMAGES.mkdir(exist_ok=True, parents=True)


def define_env(env: "MacrosPlugin"):
    @env.macro
    @pass_context
    def show_widget(context, width: int = 500) -> list[Path]:
        # extract all fenced code blocks starting with "python"
        page = context["page"]
        dest = IMAGES / f"{page.title}.png"
        if "build" in sys.argv:
            dest.unlink(missing_ok=True)

            codeblocks = [
                b[6:].strip()
                for b in page.markdown.split("```")
                if b.startswith("python")
            ]
            src = codeblocks[0].strip()
            src = src.replace(
                "QApplication([])", "QApplication.instance() or QApplication([])"
            )
            src = src.replace("app.exec_()", "app.processEvents()")

            exec(src)
            _grab(dest, width)
        return (
            f"![{page.title}](../{dest.parent.name}/{dest.name})"
            f"{{ loading=lazy; width={width} }}\n\n"
        )

    @env.macro
    def show_members(cls: str):
        # import class
        module, name = cls.rsplit(".", 1)
        _cls = getattr(import_module(module), name)

        first_q = next(
            (
                b.__name__
                for b in _cls.__mro__
                if issubclass(b, QObject) and ".Qt" in b.__module__
            ),
            None,
        )

        inherited_members = set()
        for base in _cls.__mro__:
            if issubclass(base, QObject) and ".Qt" in base.__module__:
                inherited_members.update(
                    {k for k in dir(base) if not k.startswith("_")}
                )

        new_signals = {
            k
            for k, v in vars(_cls).items()
            if not k.startswith("_") and isinstance(v, Signal)
        }

        self_members = {
            k
            for k in dir(_cls)
            if not k.startswith("_") and k not in inherited_members | new_signals
        }

        enums = []
        for m in list(self_members):
            if isinstance(getattr(_cls, m), EnumMeta):
                self_members.remove(m)
                enums.append(m)

        out = ""
        if first_q:
            url = f"https://doc.qt.io/qt-6/{first_q.lower()}.html"
            out += f"## Qt Class\n\n<a href='{url}'>`{first_q}`</a>\n\n"

        out += ""

        if new_signals:
            out += "## Signals\n\n"
            for sig in new_signals:
                out += f"### `{sig}`\n\n"

        if enums:
            out += "## Enums\n\n"
            for e in enums:
                out += f"### `{_cls.__name__}.{e}`\n\n"
                for m in getattr(_cls, e):
                    out += f"- `{m.name}`\n\n"

        if self_members:
            out += dedent(
                f"""
            ## Methods

            ::: {cls}
                options:
                  heading_level: 3
                  show_source: False
                  show_inherited_members: false
                  show_signature_annotations: True
                  members: {sorted(self_members)}
                  docstring_style: numpy
                  show_bases: False
                  show_root_toc_entry: False
                  show_root_heading: False
            """
            )

        return out


def _grab(dest: str | Path, width) -> list[Path]:
    """Grab the top widgets of the application."""
    from qtpy.QtWidgets import QApplication

    w = QApplication.topLevelWidgets()[-1]
    w.setFixedWidth(width)
    w.activateWindow()
    w.setMinimumHeight(40)
    w.grab().save(str(dest))