python-docs-theme 2024.12__tar.gz → 2025.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/PKG-INFO +8 -7
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/README.md +1 -0
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/pyproject.toml +13 -7
- python_docs_theme-2025.4/python_docs_theme/__init__.py +24 -0
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/footerdonate.html +1 -1
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/layout.html +17 -17
- python_docs_theme-2025.4/python_docs_theme/static/copybutton.js +84 -0
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/pydoctheme.css +31 -30
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/pydoctheme_dark.css +13 -0
- python_docs_theme-2025.4/python_docs_theme/theme.toml +39 -0
- python_docs_theme-2024.12/python_docs_theme/__init__.py +0 -64
- python_docs_theme-2024.12/python_docs_theme/static/copybutton.js +0 -92
- python_docs_theme-2024.12/python_docs_theme/static/sidebar.js_t +0 -95
- python_docs_theme-2024.12/python_docs_theme/theme.conf +0 -37
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/LICENSE +0 -0
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/menu.js +0 -0
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/py.png +0 -0
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/py.svg +0 -0
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/search-focus.js +0 -0
- {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/themetoggle.js +0 -0
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: python-docs-theme
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2025.4
|
|
4
4
|
Summary: The Sphinx theme for the CPython docs and related projects
|
|
5
5
|
Author-email: PyPA <distutils-sig@python.org>
|
|
6
|
-
Requires-Python: >=3.
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
|
+
License-Expression: PSF-2.0
|
|
8
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
9
10
|
Classifier: Framework :: Sphinx :: Theme
|
|
10
11
|
Classifier: Intended Audience :: Developers
|
|
11
|
-
Classifier: License :: OSI Approved :: Python Software Foundation License
|
|
12
12
|
Classifier: Operating System :: OS Independent
|
|
13
13
|
Classifier: Programming Language :: Python
|
|
14
14
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
18
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
18
|
Classifier: Topic :: Documentation
|
|
21
19
|
Classifier: Topic :: Software Development :: Documentation
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: sphinx>=7.3
|
|
22
22
|
Project-URL: Code, https://github.com/python/python-docs-theme
|
|
23
23
|
Project-URL: Download, https://pypi.org/project/python-docs-theme/
|
|
24
24
|
Project-URL: Homepage, https://github.com/python/python-docs-theme/
|
|
@@ -27,6 +27,7 @@ Project-URL: Issue tracker, https://github.com/python/python-docs-theme/issues
|
|
|
27
27
|
# Python Docs Sphinx Theme
|
|
28
28
|
|
|
29
29
|
This is the theme for the Python documentation.
|
|
30
|
+
It requires Python 3.12 or newer and Sphinx 7.3 or newer.
|
|
30
31
|
|
|
31
32
|
Note that when adopting this theme, you're also borrowing an element of the
|
|
32
33
|
trust and credibility established by the CPython core developers over the
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Python Docs Sphinx Theme
|
|
2
2
|
|
|
3
3
|
This is the theme for the Python documentation.
|
|
4
|
+
It requires Python 3.12 or newer and Sphinx 7.3 or newer.
|
|
4
5
|
|
|
5
6
|
Note that when adopting this theme, you're also borrowing an element of the
|
|
6
7
|
trust and credibility established by the CPython core developers over the
|
|
@@ -6,28 +6,31 @@ requires = [
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "python-docs-theme"
|
|
9
|
-
version = "2024.12"
|
|
10
9
|
description = "The Sphinx theme for the CPython docs and related projects"
|
|
11
10
|
readme = "README.md"
|
|
12
|
-
license
|
|
11
|
+
license = "PSF-2.0"
|
|
12
|
+
license-files = [ "LICENSE" ]
|
|
13
13
|
authors = [ { name = "PyPA", email = "distutils-sig@python.org" } ]
|
|
14
|
-
requires-python = ">=3.
|
|
14
|
+
requires-python = ">=3.12"
|
|
15
15
|
classifiers = [
|
|
16
16
|
"Development Status :: 5 - Production/Stable",
|
|
17
17
|
"Framework :: Sphinx :: Theme",
|
|
18
18
|
"Intended Audience :: Developers",
|
|
19
|
-
"License :: OSI Approved :: Python Software Foundation License",
|
|
20
19
|
"Operating System :: OS Independent",
|
|
21
20
|
"Programming Language :: Python",
|
|
22
21
|
"Programming Language :: Python :: 3 :: Only",
|
|
23
|
-
"Programming Language :: Python :: 3.9",
|
|
24
|
-
"Programming Language :: Python :: 3.10",
|
|
25
|
-
"Programming Language :: Python :: 3.11",
|
|
26
22
|
"Programming Language :: Python :: 3.12",
|
|
27
23
|
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Programming Language :: Python :: 3.14",
|
|
28
25
|
"Topic :: Documentation",
|
|
29
26
|
"Topic :: Software Development :: Documentation",
|
|
30
27
|
]
|
|
28
|
+
dynamic = [ "version" ]
|
|
29
|
+
|
|
30
|
+
dependencies = [
|
|
31
|
+
"sphinx>=7.3",
|
|
32
|
+
]
|
|
33
|
+
|
|
31
34
|
urls.Code = "https://github.com/python/python-docs-theme"
|
|
32
35
|
urls.Download = "https://pypi.org/project/python-docs-theme/"
|
|
33
36
|
urls.Homepage = "https://github.com/python/python-docs-theme/"
|
|
@@ -65,3 +68,6 @@ lint.ignore = [
|
|
|
65
68
|
"E241", # Multiple spaces after ','
|
|
66
69
|
]
|
|
67
70
|
lint.isort.required-imports = [ "from __future__ import annotations" ]
|
|
71
|
+
|
|
72
|
+
[tool.pyproject-fmt]
|
|
73
|
+
max_supported_python = "3.14"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
TYPE_CHECKING = False
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from sphinx.application import Sphinx
|
|
8
|
+
from sphinx.util.typing import ExtensionMetadata
|
|
9
|
+
|
|
10
|
+
__version__ = "2025.4"
|
|
11
|
+
|
|
12
|
+
THEME_PATH = Path(__file__).resolve().parent
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def setup(app: Sphinx) -> ExtensionMetadata:
|
|
16
|
+
app.require_sphinx("7.3")
|
|
17
|
+
|
|
18
|
+
app.add_html_theme("python_docs_theme", str(THEME_PATH))
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
"version": __version__,
|
|
22
|
+
"parallel_read_safe": True,
|
|
23
|
+
"parallel_write_safe": True,
|
|
24
|
+
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
</li>
|
|
15
15
|
{%- endfor %}
|
|
16
16
|
{%- block rootrellink %}
|
|
17
|
-
<li><img src="{{ pathto('_static/' ~ theme_root_icon, 1) }}" alt="{{ theme_root_icon_alt_text }}" style="vertical-align: middle; margin-top: -1px"
|
|
17
|
+
<li><img src="{{ pathto('_static/' ~ theme_root_icon, 1) }}" alt="{{ theme_root_icon_alt_text }}" style="vertical-align: middle; margin-top: -1px"></li>
|
|
18
18
|
<li><a href="{{theme_root_url}}">{{theme_root_name}}</a>{{ reldelim1 }}</li>
|
|
19
19
|
<li class="switchers">
|
|
20
20
|
<div class="language_switcher_placeholder"></div>
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
{%- if builder != "htmlhelp" %}
|
|
49
49
|
<div class="inline-search" role="search">
|
|
50
50
|
<form class="inline-search" action="{{ pathto('search') }}" method="get">
|
|
51
|
-
<input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q" id="search-box"
|
|
52
|
-
<input type="submit" value="{{ _('Go') }}"
|
|
51
|
+
<input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q" id="search-box">
|
|
52
|
+
<input type="submit" value="{{ _('Go') }}">
|
|
53
53
|
</form>
|
|
54
54
|
</div>
|
|
55
55
|
{%- endif %}
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
|
|
72
72
|
{%- block extrahead -%}
|
|
73
73
|
<link rel="stylesheet" href="{{ pathto('_static/pydoctheme_dark.css', 1) }}" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css">
|
|
74
|
-
<link rel="shortcut icon" type="image/png" href="{{ pathto('_static/' ~ theme_root_icon, 1) }}"
|
|
74
|
+
<link rel="shortcut icon" type="image/png" href="{{ pathto('_static/' ~ theme_root_icon, 1) }}">
|
|
75
75
|
{%- if builder != "htmlhelp" %}
|
|
76
76
|
{%- if not embedded %}
|
|
77
77
|
<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>
|
|
@@ -93,14 +93,14 @@
|
|
|
93
93
|
{%- if builder != 'htmlhelp' %}
|
|
94
94
|
<div class="mobile-nav">
|
|
95
95
|
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
|
|
96
|
-
aria-pressed="false" aria-expanded="false" role="button" aria-label="{{ _('Menu')}}"
|
|
96
|
+
aria-pressed="false" aria-expanded="false" role="button" aria-label="{{ _('Menu')}}">
|
|
97
97
|
<nav class="nav-content" role="navigation">
|
|
98
98
|
<label for="menuToggler" class="toggler__label">
|
|
99
99
|
<span></span>
|
|
100
100
|
</label>
|
|
101
101
|
<span class="nav-items-wrapper">
|
|
102
102
|
<a href="{{ theme_root_url }}" class="nav-logo">
|
|
103
|
-
<img src="{{ pathto('_static/' ~ theme_root_icon, 1) }}" alt="{{ theme_root_icon_alt_text }}"
|
|
103
|
+
<img src="{{ pathto('_static/' ~ theme_root_icon, 1) }}" alt="{{ theme_root_icon_alt_text }}">
|
|
104
104
|
</a>
|
|
105
105
|
<span class="version_switcher_placeholder"></span>
|
|
106
106
|
{%- if pagename != "search" and builder != "singlehtml" %}
|
|
@@ -108,8 +108,8 @@
|
|
|
108
108
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
|
|
109
109
|
<path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
|
|
110
110
|
</svg>
|
|
111
|
-
<input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q"
|
|
112
|
-
<input type="submit" value="{{ _('Go') }}"
|
|
111
|
+
<input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q">
|
|
112
|
+
<input type="submit" value="{{ _('Go') }}">
|
|
113
113
|
</form>
|
|
114
114
|
{%- endif %}
|
|
115
115
|
</span>
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
{%- if logo %}
|
|
122
122
|
<p class="logo">
|
|
123
123
|
<a href="{{ pathto('index') }}">
|
|
124
|
-
<img class="logo" src="{{ pathto('_static/' ~ logo, 1)|e }}" alt="Logo"
|
|
124
|
+
<img class="logo" src="{{ pathto('_static/' ~ logo, 1)|e }}" alt="Logo">
|
|
125
125
|
</a>
|
|
126
126
|
</p>
|
|
127
127
|
{%- endif %}
|
|
@@ -143,21 +143,21 @@
|
|
|
143
143
|
{% if theme_copyright_url or hasdoc('copyright') %}
|
|
144
144
|
</a>
|
|
145
145
|
{% endif %} {{ copyright|e }}.
|
|
146
|
-
<br
|
|
146
|
+
<br>
|
|
147
147
|
{% trans %}This page is licensed under the Python Software Foundation License Version 2.{% endtrans %}
|
|
148
|
-
<br
|
|
148
|
+
<br>
|
|
149
149
|
{% trans %}Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.{% endtrans %}
|
|
150
|
-
<br
|
|
150
|
+
<br>
|
|
151
151
|
{% if theme_license_url %}
|
|
152
|
-
{% trans license_file=theme_license_url %}See <a href="{{ license_file }}">History and License</a> for more information.{% endtrans %}<br
|
|
152
|
+
{% trans license_file=theme_license_url %}See <a href="{{ license_file }}">History and License</a> for more information.{% endtrans %}<br>
|
|
153
153
|
{% endif %}
|
|
154
154
|
{% if theme_hosted_on %}
|
|
155
|
-
{% trans hosted_on=theme_hosted_on %}Hosted on {{ hosted_on }}.{% endtrans %}<br
|
|
155
|
+
{% trans hosted_on=theme_hosted_on %}Hosted on {{ hosted_on }}.{% endtrans %}<br>
|
|
156
156
|
{% endif %}
|
|
157
|
-
<br
|
|
157
|
+
<br>
|
|
158
158
|
|
|
159
159
|
{% include "footerdonate.html" %}
|
|
160
|
-
<br
|
|
160
|
+
<br>
|
|
161
161
|
|
|
162
162
|
{%- if last_updated %}
|
|
163
163
|
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
{% if theme_issues_url %}
|
|
166
166
|
{% trans %}<a href="{{ theme_issues_url }}">Found a bug</a>?{% endtrans %}
|
|
167
167
|
{% endif %}
|
|
168
|
-
<br
|
|
168
|
+
<br>
|
|
169
169
|
|
|
170
170
|
{% trans sphinx_version=sphinx_version|e %}Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
|
|
171
171
|
</div>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Extract copyable text from the code block ignoring the
|
|
2
|
+
// prompts and output.
|
|
3
|
+
function getCopyableText(rootElement) {
|
|
4
|
+
rootElement = rootElement.cloneNode(true)
|
|
5
|
+
// tracebacks (.gt) contain bare text elements that
|
|
6
|
+
// need to be removed
|
|
7
|
+
const tracebacks = rootElement.querySelectorAll(".gt")
|
|
8
|
+
for (const el of tracebacks) {
|
|
9
|
+
while (
|
|
10
|
+
el.nextSibling &&
|
|
11
|
+
(el.nextSibling.nodeType !== Node.DOCUMENT_NODE ||
|
|
12
|
+
!el.nextSibling.matches(".gp, .go"))
|
|
13
|
+
) {
|
|
14
|
+
el.nextSibling.remove()
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// Remove all elements with the "go" (Generic.Output),
|
|
18
|
+
// "gp" (Generic.Prompt), or "gt" (Generic.Traceback) CSS class
|
|
19
|
+
const elements = rootElement.querySelectorAll(".gp, .go, .gt")
|
|
20
|
+
for (const el of elements) {
|
|
21
|
+
el.remove()
|
|
22
|
+
}
|
|
23
|
+
return rootElement.innerText.trim()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const loadCopyButton = () => {
|
|
27
|
+
const button = document.createElement("button")
|
|
28
|
+
button.classList.add("copybutton")
|
|
29
|
+
button.type = "button"
|
|
30
|
+
button.innerText = _("Copy")
|
|
31
|
+
button.title = _("Copy to clipboard")
|
|
32
|
+
|
|
33
|
+
const makeOnButtonClick = () => {
|
|
34
|
+
let timeout = null
|
|
35
|
+
// define the behavior of the button when it's clicked
|
|
36
|
+
return async event => {
|
|
37
|
+
// check if the clipboard is available
|
|
38
|
+
if (!navigator.clipboard || !navigator.clipboard.writeText) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
clearTimeout(timeout)
|
|
43
|
+
const buttonEl = event.currentTarget
|
|
44
|
+
const codeEl = buttonEl.nextElementSibling
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
await navigator.clipboard.writeText(getCopyableText(codeEl))
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.error(e.message)
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
buttonEl.innerText = _("Copied!")
|
|
54
|
+
timeout = setTimeout(() => {
|
|
55
|
+
buttonEl.innerText = _("Copy")
|
|
56
|
+
}, 1500)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const highlightedElements = document.querySelectorAll(
|
|
61
|
+
".highlight-python .highlight,"
|
|
62
|
+
+ ".highlight-python3 .highlight,"
|
|
63
|
+
+ ".highlight-pycon .highlight,"
|
|
64
|
+
+ ".highlight-pycon3 .highlight,"
|
|
65
|
+
+ ".highlight-default .highlight"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
// create and add the button to all the code blocks that contain >>>
|
|
69
|
+
highlightedElements.forEach(el => {
|
|
70
|
+
el.style.position = "relative"
|
|
71
|
+
|
|
72
|
+
// if we find a console prompt (.gp), prepend the (deeply cloned) button
|
|
73
|
+
const clonedButton = button.cloneNode(true)
|
|
74
|
+
// the onclick attribute is not cloned, set it on the new element
|
|
75
|
+
clonedButton.onclick = makeOnButtonClick()
|
|
76
|
+
el.prepend(clonedButton)
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (document.readyState !== "loading") {
|
|
81
|
+
loadCopyButton()
|
|
82
|
+
} else {
|
|
83
|
+
document.addEventListener("DOMContentLoaded", loadCopyButton)
|
|
84
|
+
}
|
{python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/pydoctheme.css
RENAMED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
@import url('classic.css');
|
|
2
|
-
|
|
3
1
|
/* Common colours */
|
|
4
2
|
:root {
|
|
5
3
|
--good-color: rgb(41 100 51);
|
|
@@ -140,6 +138,8 @@ span.pre {
|
|
|
140
138
|
}
|
|
141
139
|
|
|
142
140
|
div.sphinxsidebar {
|
|
141
|
+
display: flex;
|
|
142
|
+
width: min(25vw, 350px);
|
|
143
143
|
float: none;
|
|
144
144
|
position: sticky;
|
|
145
145
|
top: 0;
|
|
@@ -156,13 +156,17 @@ div.sphinxsidebar h4 {
|
|
|
156
156
|
margin-top: 1.5em;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
div.bodywrapper {
|
|
160
|
+
margin-left: min(25vw, 350px);
|
|
161
|
+
}
|
|
162
|
+
|
|
159
163
|
div.sphinxsidebarwrapper {
|
|
160
|
-
width: 217px;
|
|
161
164
|
box-sizing: border-box;
|
|
162
165
|
height: 100%;
|
|
163
166
|
overflow-x: hidden;
|
|
164
167
|
overflow-y: auto;
|
|
165
|
-
float:
|
|
168
|
+
float: none;
|
|
169
|
+
flex-grow: 1;
|
|
166
170
|
}
|
|
167
171
|
|
|
168
172
|
div.sphinxsidebarwrapper > h3:first-child {
|
|
@@ -191,28 +195,15 @@ div.sphinxsidebar input[type='text'] {
|
|
|
191
195
|
}
|
|
192
196
|
|
|
193
197
|
#sidebarbutton {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
margin-left: 0;
|
|
198
|
-
color: #444444;
|
|
199
|
-
font-size: 1.2em;
|
|
200
|
-
cursor: pointer;
|
|
201
|
-
padding-top: 1px;
|
|
202
|
-
float: right;
|
|
203
|
-
display: table;
|
|
204
|
-
/* after Sphinx 4.x and earlier is dropped, only the below is needed */
|
|
198
|
+
display: flex;
|
|
199
|
+
justify-content: center;
|
|
200
|
+
align-items: center;
|
|
205
201
|
width: 12px;
|
|
202
|
+
min-width: 12px;
|
|
206
203
|
border-radius: 0 5px 5px 0;
|
|
207
204
|
border-left: none;
|
|
208
205
|
}
|
|
209
206
|
|
|
210
|
-
#sidebarbutton span {
|
|
211
|
-
/* Sphinx 4.x and earlier compat */
|
|
212
|
-
display: table-cell;
|
|
213
|
-
vertical-align: middle;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
207
|
#sidebarbutton:hover {
|
|
217
208
|
background-color: #AAAAAA;
|
|
218
209
|
}
|
|
@@ -337,6 +328,10 @@ tt, code, pre {
|
|
|
337
328
|
font-size: 96.5%;
|
|
338
329
|
}
|
|
339
330
|
|
|
331
|
+
div.body pre {
|
|
332
|
+
line-height: 120%;
|
|
333
|
+
}
|
|
334
|
+
|
|
340
335
|
div.body tt,
|
|
341
336
|
div.body code {
|
|
342
337
|
border-radius: 3px;
|
|
@@ -447,17 +442,23 @@ div.genindex-jumpbox a {
|
|
|
447
442
|
top: 0;
|
|
448
443
|
right: 0;
|
|
449
444
|
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
|
450
|
-
|
|
451
|
-
padding-
|
|
445
|
+
font-size: 80%;
|
|
446
|
+
padding-left: .5em;
|
|
447
|
+
padding-right: .5em;
|
|
448
|
+
height: 100%;
|
|
449
|
+
max-height: min(100%, 2.4em);
|
|
452
450
|
border-radius: 0 3px 0 0;
|
|
453
|
-
color: #
|
|
454
|
-
|
|
455
|
-
border
|
|
456
|
-
|
|
451
|
+
color: #000;
|
|
452
|
+
background-color: #fff;
|
|
453
|
+
border: 1px solid #ac9; /* follows div.body pre */
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.copybutton:hover {
|
|
457
|
+
background-color: #eee;
|
|
457
458
|
}
|
|
458
459
|
|
|
459
|
-
.copybutton
|
|
460
|
-
|
|
460
|
+
.copybutton:active {
|
|
461
|
+
background-color: #ddd;
|
|
461
462
|
}
|
|
462
463
|
|
|
463
464
|
@media (max-width: 1023px) {
|
|
@@ -489,7 +490,7 @@ div.genindex-jumpbox a {
|
|
|
489
490
|
margin-inline-end: 0;
|
|
490
491
|
}
|
|
491
492
|
/* Remove sidebar and top related bar */
|
|
492
|
-
div.related, .sphinxsidebar {
|
|
493
|
+
div.related, div.sphinxsidebar {
|
|
493
494
|
display: none;
|
|
494
495
|
}
|
|
495
496
|
/* Anchorlinks are not hidden by fixed-positioned navbar when scrolled to */
|
{python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/pydoctheme_dark.css
RENAMED
|
@@ -176,3 +176,16 @@ img.invert-in-dark-mode {
|
|
|
176
176
|
--versionchanged: var(--middle-color);
|
|
177
177
|
--deprecated: var(--bad-color);
|
|
178
178
|
}
|
|
179
|
+
|
|
180
|
+
.copybutton {
|
|
181
|
+
color: #ac9; /* follows div.body pre */
|
|
182
|
+
background-color: #222222; /* follows body */
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.copybutton:hover {
|
|
186
|
+
background-color: #434343;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.copybutton:active {
|
|
190
|
+
background-color: #656565;
|
|
191
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[theme]
|
|
2
|
+
inherit = "default"
|
|
3
|
+
stylesheets = [
|
|
4
|
+
"classic.css",
|
|
5
|
+
"pydoctheme.css",
|
|
6
|
+
]
|
|
7
|
+
pygments_style = { default = "default", dark = "monokai" }
|
|
8
|
+
|
|
9
|
+
[options]
|
|
10
|
+
bodyfont = "-apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif"
|
|
11
|
+
headfont = "-apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif"
|
|
12
|
+
footerbgcolor = "white"
|
|
13
|
+
footertextcolor = "#555555"
|
|
14
|
+
relbarbgcolor = "white"
|
|
15
|
+
relbartextcolor = "#666666"
|
|
16
|
+
relbarlinkcolor = "#444444"
|
|
17
|
+
sidebarbgcolor = "white"
|
|
18
|
+
sidebartextcolor = "#444444"
|
|
19
|
+
sidebarlinkcolor = "#444444"
|
|
20
|
+
sidebarbtncolor = "#cccccc"
|
|
21
|
+
bgcolor = "white"
|
|
22
|
+
textcolor = "#222222"
|
|
23
|
+
linkcolor = "#0090c0"
|
|
24
|
+
visitedlinkcolor = "#00608f"
|
|
25
|
+
headtextcolor = "#1a1a1a"
|
|
26
|
+
headbgcolor = "white"
|
|
27
|
+
headlinkcolor = "#aaaaaa"
|
|
28
|
+
codebgcolor = "#eeffcc"
|
|
29
|
+
codetextcolor = "#333333"
|
|
30
|
+
|
|
31
|
+
hosted_on = ""
|
|
32
|
+
issues_url = ""
|
|
33
|
+
license_url = ""
|
|
34
|
+
root_name = "Python"
|
|
35
|
+
root_url = "https://www.python.org/"
|
|
36
|
+
root_icon = "py.svg"
|
|
37
|
+
root_icon_alt_text = "Python logo"
|
|
38
|
+
root_include_title = "True"
|
|
39
|
+
copyright_url = ""
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import hashlib
|
|
4
|
-
import os
|
|
5
|
-
from functools import cache
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from typing import Any
|
|
8
|
-
|
|
9
|
-
import sphinx.application
|
|
10
|
-
from sphinx.builders.html import StandaloneHTMLBuilder
|
|
11
|
-
|
|
12
|
-
THEME_PATH = Path(__file__).parent.resolve()
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@cache
|
|
16
|
-
def _asset_hash(path: str) -> str:
|
|
17
|
-
"""Append a `?digest=` to an url based on the file content."""
|
|
18
|
-
full_path = THEME_PATH / path.replace("_static/", "static/")
|
|
19
|
-
digest = hashlib.sha1(full_path.read_bytes()).hexdigest()
|
|
20
|
-
|
|
21
|
-
return f"{path}?digest={digest}"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def _add_asset_hashes(static: list[str], add_digest_to: list[str]) -> None:
|
|
25
|
-
for asset in add_digest_to:
|
|
26
|
-
index = static.index(asset)
|
|
27
|
-
static[index].filename = _asset_hash(asset) # type: ignore[attr-defined]
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def _html_page_context(
|
|
31
|
-
app: sphinx.application.Sphinx,
|
|
32
|
-
pagename: str,
|
|
33
|
-
templatename: str,
|
|
34
|
-
context: dict[str, Any],
|
|
35
|
-
doctree: Any,
|
|
36
|
-
) -> None:
|
|
37
|
-
if app.config.html_theme != "python_docs_theme":
|
|
38
|
-
return
|
|
39
|
-
|
|
40
|
-
assert isinstance(app.builder, StandaloneHTMLBuilder)
|
|
41
|
-
|
|
42
|
-
if (4,) <= sphinx.version_info < (7, 1) and "css_files" in context:
|
|
43
|
-
if "_static/pydoctheme.css" not in context["css_files"]:
|
|
44
|
-
raise ValueError(
|
|
45
|
-
"This documentation is not using `pydoctheme.css` as the stylesheet. "
|
|
46
|
-
"If you have set `html_style` in your conf.py file, remove it."
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
_add_asset_hashes(
|
|
50
|
-
context["css_files"],
|
|
51
|
-
["_static/pydoctheme.css"],
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def setup(app):
|
|
56
|
-
current_dir = os.path.abspath(os.path.dirname(__file__))
|
|
57
|
-
app.add_html_theme("python_docs_theme", current_dir)
|
|
58
|
-
|
|
59
|
-
app.connect("html-page-context", _html_page_context)
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
"parallel_read_safe": True,
|
|
63
|
-
"parallel_write_safe": True,
|
|
64
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
// ``function*`` denotes a generator in JavaScript, see
|
|
2
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
|
|
3
|
-
function* getHideableCopyButtonElements(rootElement) {
|
|
4
|
-
// yield all elements with the "go" (Generic.Output),
|
|
5
|
-
// "gp" (Generic.Prompt), or "gt" (Generic.Traceback) CSS class
|
|
6
|
-
for (const el of rootElement.querySelectorAll('.go, .gp, .gt')) {
|
|
7
|
-
yield el
|
|
8
|
-
}
|
|
9
|
-
// tracebacks (.gt) contain bare text elements that need to be
|
|
10
|
-
// wrapped in a span to hide or show the element
|
|
11
|
-
for (let el of rootElement.querySelectorAll('.gt')) {
|
|
12
|
-
while ((el = el.nextSibling) && el.nodeType !== Node.DOCUMENT_NODE) {
|
|
13
|
-
// stop wrapping text nodes when we hit the next output or
|
|
14
|
-
// prompt element
|
|
15
|
-
if (el.nodeType === Node.ELEMENT_NODE && el.matches(".gp, .go")) {
|
|
16
|
-
break
|
|
17
|
-
}
|
|
18
|
-
// if the node is a text node with content, wrap it in a
|
|
19
|
-
// span element so that we can control visibility
|
|
20
|
-
if (el.nodeType === Node.TEXT_NODE && el.textContent.trim()) {
|
|
21
|
-
const wrapper = document.createElement("span")
|
|
22
|
-
el.after(wrapper)
|
|
23
|
-
wrapper.appendChild(el)
|
|
24
|
-
el = wrapper
|
|
25
|
-
}
|
|
26
|
-
yield el
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const loadCopyButton = () => {
|
|
33
|
-
/* Add a [>>>] button in the top-right corner of code samples to hide
|
|
34
|
-
* the >>> and ... prompts and the output and thus make the code
|
|
35
|
-
* copyable. */
|
|
36
|
-
const hide_text = "Hide the prompts and output"
|
|
37
|
-
const show_text = "Show the prompts and output"
|
|
38
|
-
|
|
39
|
-
const button = document.createElement("span")
|
|
40
|
-
button.classList.add("copybutton")
|
|
41
|
-
button.innerText = ">>>"
|
|
42
|
-
button.title = hide_text
|
|
43
|
-
button.dataset.hidden = "false"
|
|
44
|
-
const buttonClick = event => {
|
|
45
|
-
// define the behavior of the button when it's clicked
|
|
46
|
-
event.preventDefault()
|
|
47
|
-
const buttonEl = event.currentTarget
|
|
48
|
-
const codeEl = buttonEl.nextElementSibling
|
|
49
|
-
if (buttonEl.dataset.hidden === "false") {
|
|
50
|
-
// hide the code output
|
|
51
|
-
for (const el of getHideableCopyButtonElements(codeEl)) {
|
|
52
|
-
el.hidden = true
|
|
53
|
-
}
|
|
54
|
-
buttonEl.title = show_text
|
|
55
|
-
buttonEl.dataset.hidden = "true"
|
|
56
|
-
} else {
|
|
57
|
-
// show the code output
|
|
58
|
-
for (const el of getHideableCopyButtonElements(codeEl)) {
|
|
59
|
-
el.hidden = false
|
|
60
|
-
}
|
|
61
|
-
buttonEl.title = hide_text
|
|
62
|
-
buttonEl.dataset.hidden = "false"
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const highlightedElements = document.querySelectorAll(
|
|
67
|
-
".highlight-python .highlight,"
|
|
68
|
-
+ ".highlight-python3 .highlight,"
|
|
69
|
-
+ ".highlight-pycon .highlight,"
|
|
70
|
-
+ ".highlight-pycon3 .highlight,"
|
|
71
|
-
+ ".highlight-default .highlight"
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
// create and add the button to all the code blocks that contain >>>
|
|
75
|
-
highlightedElements.forEach(el => {
|
|
76
|
-
el.style.position = "relative"
|
|
77
|
-
|
|
78
|
-
// if we find a console prompt (.gp), prepend the (deeply cloned) button
|
|
79
|
-
const clonedButton = button.cloneNode(true)
|
|
80
|
-
// the onclick attribute is not cloned, set it on the new element
|
|
81
|
-
clonedButton.onclick = buttonClick
|
|
82
|
-
if (el.querySelector(".gp") !== null) {
|
|
83
|
-
el.prepend(clonedButton)
|
|
84
|
-
}
|
|
85
|
-
})
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (document.readyState !== "loading") {
|
|
89
|
-
loadCopyButton()
|
|
90
|
-
} else {
|
|
91
|
-
document.addEventListener("DOMContentLoaded", loadCopyButton)
|
|
92
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* sidebar.js
|
|
3
|
-
* ~~~~~~~~~~
|
|
4
|
-
*
|
|
5
|
-
* This file is functionally identical to "sidebar.js" in Sphinx 5.0.
|
|
6
|
-
* When support for Sphinx 4 and earlier is dropped from the theme,
|
|
7
|
-
* this file can be removed.
|
|
8
|
-
*
|
|
9
|
-
* This script makes the Sphinx sidebar collapsible.
|
|
10
|
-
*
|
|
11
|
-
* .sphinxsidebar contains .sphinxsidebarwrapper. This script adds
|
|
12
|
-
* in .sphinxsidebar, after .sphinxsidebarwrapper, the #sidebarbutton
|
|
13
|
-
* used to collapse and expand the sidebar.
|
|
14
|
-
*
|
|
15
|
-
* When the sidebar is collapsed the .sphinxsidebarwrapper is hidden
|
|
16
|
-
* and the width of the sidebar and the margin-left of the document
|
|
17
|
-
* are decreased. When the sidebar is expanded the opposite happens.
|
|
18
|
-
* This script saves a per-browser/per-session cookie used to
|
|
19
|
-
* remember the position of the sidebar among the pages.
|
|
20
|
-
* Once the browser is closed the cookie is deleted and the position
|
|
21
|
-
* reset to the default (expanded).
|
|
22
|
-
*
|
|
23
|
-
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
|
|
24
|
-
* :license: BSD, see LICENSE for details.
|
|
25
|
-
*
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
const initialiseSidebar = () => {
|
|
29
|
-
// global elements used by the functions.
|
|
30
|
-
const bodyWrapper = document.getElementsByClassName("bodywrapper")[0]
|
|
31
|
-
const sidebar = document.getElementsByClassName("sphinxsidebar")[0]
|
|
32
|
-
const sidebarWrapper = document.getElementsByClassName("sphinxsidebarwrapper")[0]
|
|
33
|
-
|
|
34
|
-
// exit early if the document has no sidebar for some reason
|
|
35
|
-
if (typeof sidebar === "undefined") {
|
|
36
|
-
return
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
{# Check if we need to dynamically insert the sidebar button.
|
|
40
|
-
# We prefer the ``sphinx_version_tuple`` variable, and if it is undefined we
|
|
41
|
-
# know we are running a Sphinx version older than 4.2.
|
|
42
|
-
#
|
|
43
|
-
# See: https://www.sphinx-doc.org/en/master/development/templating.html#sphinx_version_tuple
|
|
44
|
-
#}
|
|
45
|
-
{% if sphinx_version_tuple is defined and sphinx_version_tuple[0] >= 5 %}
|
|
46
|
-
const sidebarButton = document.getElementById("sidebarbutton")
|
|
47
|
-
const sidebarArrow = sidebarButton.querySelector('span')
|
|
48
|
-
{% else %}
|
|
49
|
-
// create the sidebar button element
|
|
50
|
-
const sidebarButton = document.createElement("div")
|
|
51
|
-
sidebarButton.id = "sidebarbutton"
|
|
52
|
-
// create the sidebar button arrow element
|
|
53
|
-
const sidebarArrow = document.createElement("span")
|
|
54
|
-
sidebarArrow.innerText = "«"
|
|
55
|
-
sidebarButton.appendChild(sidebarArrow)
|
|
56
|
-
sidebar.appendChild(sidebarButton)
|
|
57
|
-
{% endif %}
|
|
58
|
-
|
|
59
|
-
const collapse_sidebar = () => {
|
|
60
|
-
bodyWrapper.style.marginLeft = ".8em"
|
|
61
|
-
sidebar.style.width = ".8em"
|
|
62
|
-
sidebarWrapper.style.display = "none"
|
|
63
|
-
sidebarArrow.innerText = "»"
|
|
64
|
-
sidebarButton.title = _("Expand sidebar")
|
|
65
|
-
window.localStorage.setItem("sidebar", "collapsed")
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const expand_sidebar = () => {
|
|
69
|
-
bodyWrapper.style.marginLeft = ""
|
|
70
|
-
sidebar.style.removeProperty("width")
|
|
71
|
-
sidebarWrapper.style.display = ""
|
|
72
|
-
sidebarArrow.innerText = "«"
|
|
73
|
-
sidebarButton.title = _("Collapse sidebar")
|
|
74
|
-
window.localStorage.setItem("sidebar", "expanded")
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
sidebarButton.addEventListener("click", () => {
|
|
78
|
-
(sidebarWrapper.style.display === "none") ? expand_sidebar() : collapse_sidebar()
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
const sidebar_state = window.localStorage.getItem("sidebar")
|
|
82
|
-
if (sidebar_state === "collapsed") {
|
|
83
|
-
collapse_sidebar()
|
|
84
|
-
}
|
|
85
|
-
else if (sidebar_state === "expanded") {
|
|
86
|
-
expand_sidebar()
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (document.readyState !== "loading") {
|
|
91
|
-
initialiseSidebar()
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
document.addEventListener("DOMContentLoaded", initialiseSidebar)
|
|
95
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
[theme]
|
|
2
|
-
inherit = default
|
|
3
|
-
stylesheet = pydoctheme.css
|
|
4
|
-
pygments_style = default
|
|
5
|
-
pygments_dark_style = monokai
|
|
6
|
-
|
|
7
|
-
[options]
|
|
8
|
-
bodyfont = -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif
|
|
9
|
-
headfont = -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif
|
|
10
|
-
footerbgcolor = white
|
|
11
|
-
footertextcolor = #555555
|
|
12
|
-
relbarbgcolor = white
|
|
13
|
-
relbartextcolor = #666666
|
|
14
|
-
relbarlinkcolor = #444444
|
|
15
|
-
sidebarbgcolor = white
|
|
16
|
-
sidebartextcolor = #444444
|
|
17
|
-
sidebarlinkcolor = #444444
|
|
18
|
-
sidebarbtncolor = #cccccc
|
|
19
|
-
bgcolor = white
|
|
20
|
-
textcolor = #222222
|
|
21
|
-
linkcolor = #0090c0
|
|
22
|
-
visitedlinkcolor = #00608f
|
|
23
|
-
headtextcolor = #1a1a1a
|
|
24
|
-
headbgcolor = white
|
|
25
|
-
headlinkcolor = #aaaaaa
|
|
26
|
-
codebgcolor = #eeffcc
|
|
27
|
-
codetextcolor = #333333
|
|
28
|
-
|
|
29
|
-
hosted_on =
|
|
30
|
-
issues_url =
|
|
31
|
-
license_url =
|
|
32
|
-
root_name = Python
|
|
33
|
-
root_url = https://www.python.org/
|
|
34
|
-
root_icon = py.svg
|
|
35
|
-
root_icon_alt_text = Python logo
|
|
36
|
-
root_include_title = True
|
|
37
|
-
copyright_url =
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/search-focus.js
RENAMED
|
File without changes
|
{python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/themetoggle.js
RENAMED
|
File without changes
|