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.
Files changed (20) hide show
  1. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/PKG-INFO +8 -7
  2. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/README.md +1 -0
  3. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/pyproject.toml +13 -7
  4. python_docs_theme-2025.4/python_docs_theme/__init__.py +24 -0
  5. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/footerdonate.html +1 -1
  6. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/layout.html +17 -17
  7. python_docs_theme-2025.4/python_docs_theme/static/copybutton.js +84 -0
  8. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/pydoctheme.css +31 -30
  9. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/pydoctheme_dark.css +13 -0
  10. python_docs_theme-2025.4/python_docs_theme/theme.toml +39 -0
  11. python_docs_theme-2024.12/python_docs_theme/__init__.py +0 -64
  12. python_docs_theme-2024.12/python_docs_theme/static/copybutton.js +0 -92
  13. python_docs_theme-2024.12/python_docs_theme/static/sidebar.js_t +0 -95
  14. python_docs_theme-2024.12/python_docs_theme/theme.conf +0 -37
  15. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/LICENSE +0 -0
  16. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/menu.js +0 -0
  17. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/py.png +0 -0
  18. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/py.svg +0 -0
  19. {python_docs_theme-2024.12 → python_docs_theme-2025.4}/python_docs_theme/static/search-focus.js +0 -0
  20. {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.3
1
+ Metadata-Version: 2.4
2
2
  Name: python-docs-theme
3
- Version: 2024.12
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.9
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.file = "LICENSE"
11
+ license = "PSF-2.0"
12
+ license-files = [ "LICENSE" ]
13
13
  authors = [ { name = "PyPA", email = "distutils-sig@python.org" } ]
14
- requires-python = ">=3.9"
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
+ }
@@ -1,3 +1,3 @@
1
1
  {% trans %}The Python Software Foundation is a non-profit corporation.{% endtrans %}
2
2
  <a href="https://www.python.org/psf/donations/">{% trans %}Please donate.{% endtrans %}</a>
3
- <br />
3
+ <br>
@@ -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"/></li>
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
+ }
@@ -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: left;
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
- /* Sphinx 4.x and earlier compat */
195
- height: 100%;
196
- background-color: #CCCCCC;
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
- padding-left: 0.2em;
451
- padding-right: 0.2em;
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: #ac9; /* follows div.body pre */
454
- border-color: #ac9; /* follows div.body pre */
455
- border-style: solid; /* follows div.body pre */
456
- border-width: 1px; /* follows div.body pre */
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[data-hidden='true'] {
460
- text-decoration: line-through;
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 */
@@ -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 =