File: theme.py

package info (click to toggle)
rocm-docs-core 1.23.0-5
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,632 kB
  • sloc: python: 1,960; sh: 160; javascript: 152; cpp: 29; makefile: 27
file content (222 lines) | stat: -rw-r--r-- 8,153 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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
"""Module to use rocm-docs-core as a theme."""

from typing import Any

import time
from pathlib import Path

import requests
import sphinx.util.logging
from pydata_sphinx_theme.utils import (  # type: ignore[import-untyped]
    config_provided_by_user,
    get_theme_options_dict,
)
from sphinx.application import Sphinx

from rocm_docs import util
import os

logger = sphinx.util.logging.getLogger(__name__)

MAX_RETRY = 100


def _get_version_from_url(url: str) -> str:
    headers = {"User-Agent": "alexxu-amd"}
    try:
        retry_counter = 0
        response = requests.get(url, headers=headers)

        # Retry in case of failure
        while (response.status_code != 200) and (retry_counter <= MAX_RETRY):
            time.sleep(5)
            response = requests.get(url, headers=headers)

        if retry_counter > MAX_RETRY:
            raise requests.RequestException(
                "Unable to acquire version within MAX_RETRY!"
            )
        return response.text.strip()
    except requests.RequestException as e:
        print(f"Error in rocm-docs-core _get_version_from_url: {e}")
        return ""


def _add_custom_context(
    app: Sphinx,  # noqa: ARG001
    pagename: str,  # noqa: ARG001
    templatename: str,  # noqa: ARG001
    context: dict[str, str],
    doctree: object,  # noqa: ARG001
) -> None:
    if header_latest_version := os.getenv('latest_version') is None:
       header_latest_version = _get_version_from_url(
        "https://raw.githubusercontent.com/ROCm/rocm-docs-core/data/latest_version.txt"
    )
    context["header_latest_version"] = header_latest_version

    if header_release_candidate_version := os.getenv('release_candidate') is None:
       header_release_candidate_version = _get_version_from_url(
        "https://raw.githubusercontent.com/ROCm/rocm-docs-core/data/release_candidate.txt"
    )
    context["header_release_candidate_version"] = (
        header_release_candidate_version
    )

    if google_site_verification_content := os.getenv('google_site_verification') is None:
       google_site_verification_content = _get_version_from_url(
        "https://raw.githubusercontent.com/ROCm/rocm-docs-core/data/google_site_verification.txt"
    )
    context["google_site_verification_content"] = (
        google_site_verification_content
    )


def _update_repo_opts(srcdir: str, theme_opts: dict[str, Any]) -> None:
    default_branch_options: dict[str, Any] = {
        "use_edit_page_button": False,
    }
    try:
        url, branch = util.get_branch(srcdir)
        default_branch_options.update(
            {
                "repository_url": url,
                "repository_branch": branch,
                "path_to_docs": util.get_path_to_docs(srcdir),
            }
        )
    except util.InvalidGitRepositoryError:
        logger.warning("Not in a Git Directory, disabling repository buttons")

    for key, val in default_branch_options.items():
        theme_opts.setdefault(key, val)


def _update_banner(
    flavor: str, version_type: util.VersionType, theme_opts: dict[str, Any]
) -> None:
    if flavor != "rocm":
        return

    if version_type == util.VersionType.LATEST_RELEASE:
        return

    announcement_info: str
    if version_type == util.VersionType.RELEASE_CANDIDATE:
        announcement_info = "This page contains changes for a test release of ROCm. Read the <a id='rocm-banner' href='https://rocm.docs.amd.com/en/latest/'>latest Linux release of ROCm documentation</a> for your production environments."
    elif version_type == util.VersionType.OLD_RELEASE:
        announcement_info = "This is not the latest version of ROCm documentation. See <a id='rocm-banner' href='https://rocm.docs.amd.com/en/latest/'>ROCm documentation</a> for the latest version."
    elif version_type == util.VersionType.DEVELOPMENT:
        announcement_info = "This page contains proposed changes for a future release of ROCm. Read the <a id='rocm-banner' href='https://rocm.docs.amd.com/en/latest/'>latest Linux release of ROCm documentation</a> for your production environments."

    theme_opts.setdefault("announcement", announcement_info)


def _update_theme_options(app: Sphinx) -> None:
    theme_opts = get_theme_options_dict(app)
    _update_repo_opts(str(app.srcdir), theme_opts)

    supported_flavors = [
        "rocm",
        "local",
        "instinct",
        "rocm-docs-home",
        "rocm-blogs",
        "generic",
        "rocm-ds",
        "ai-developer-hub",
        "rocm-ls",
    ]
    flavor = theme_opts.get("flavor", "rocm")
    if flavor not in supported_flavors:
        logger.error(
            f'Unsupported theme flavor "{flavor}", must be one of: {supported_flavors}.\n'
            "Using flavor={supported_flavors[0]}"
        )
        flavor = supported_flavors[0]
        theme_opts["flavor"] = flavor

    # Set default generic theme options
    if flavor == "generic":
        theme_opts.setdefault("header_title", "")
        theme_opts.setdefault("header_link", "#")
        theme_opts.setdefault("version_list_link", None)
        theme_opts.setdefault("nav_secondary_items", {})
        theme_opts.setdefault("license_link", None)
        theme_opts.setdefault("license_text", "")

    theme_opts.setdefault(
        "article_header_start",
        ["components/toggle-primary-sidebar.html", "breadcrumbs.html"],
    )

    if hasattr(app.config, "projects_version_type"):
        _update_banner(flavor, app.config.projects_version_type, theme_opts)

    # Default the download, edit, and fullscreen buttons to off
    for button in ["download", "edit_page", "fullscreen"]:
        theme_opts.setdefault(f"use_{button}_button", False)

    if theme_opts.get("link_main_doc", True):
        theme_opts.setdefault("navbar_center", []).insert(
            0, "components/left-side-menu"
        )

    if header_latest_version := os.getenv('latest_version') is None:
       header_latest_version = _get_version_from_url(
        "https://raw.githubusercontent.com/ROCm/rocm-docs-core/data/latest_version.txt"
    )

    if header_release_candidate_version := os.getenv('release_candidate') is None:
       header_release_candidate_version = _get_version_from_url(
        "https://raw.githubusercontent.com/ROCm/rocm-docs-core/data/release_candidate.txt"
    )

    default_config_opts = {
        "html_show_sphinx": False,
        "html_favicon": "favicon.ico",
        "notfound_context": {"title": "404 - Page Not Found"},
        "notfound_template": "404.html",
        "html_context": {
            "header_latest_version": header_latest_version,
            "header_release_candidate_version": header_release_candidate_version,
        },
    }
    for key, default in default_config_opts.items():
        if not config_provided_by_user(app, key):
            setattr(app.config, key, default)


def setup(app: Sphinx) -> dict[str, Any]:
    """Set up the module as a Sphinx extension."""
    app.add_js_file("code_word_breaks.js", loading_method="async")
    app.add_js_file("renameVersionLinks.js", loading_method="async")
    app.add_js_file("rdcMisc.js", loading_method="async")
    app.add_js_file("theme_mode_captions.js", loading_method="async")
    app.add_js_file("search.js", loading_method="defer")
    here = Path(__file__).parent.resolve()
    theme_path = here / "rocm_docs_theme"
    app.add_html_theme("rocm_docs_theme", str(theme_path))
    for css in [
        "custom.css",
        "rocm_header.css",
        "rocm_footer.css",
        "fonts.css",
    ]:
        app.add_css_file(css)

    app.connect("html-page-context", _add_custom_context)
    app.connect("builder-inited", _update_theme_options)

    # Add theme option declarations
    app.add_config_value("header_title", "", "html")
    app.add_config_value("header_link", "#", "html")
    app.add_config_value("version_list_link", None, "html")
    app.add_config_value("nav_secondary_items", {}, "html", [dict])
    app.add_config_value("license_link", None, "html")
    app.add_config_value("license_text", "", "html")

    return {
        "parallel_read_safe": True,
        "parallel_write_safe": True,
    }