We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
CSS broken in latest docs
## 🐛 Bug

![image](https://user-images.githubusercontent.com/24893111/214972488-e914fb00-d431-4354-9bdd-bf4b67f76516.png)

It seems like the versionwarning banner is not displayed correctly in latest docs.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `docs/conf.py`
Content:
```
1 # Configuration file for the Sphinx documentation builder.
2 
3 # -- Path setup --------------------------------------------------------------
4 
5 import atexit
6 import os
7 import shutil
8 import subprocess
9 import sys
10 from pathlib import Path
11 from typing import Any
12 from unittest import mock
13 
14 import micropip
15 
16 panels_add_bootstrap_css = False
17 
18 # -- Project information -----------------------------------------------------
19 
20 project = "Pyodide"
21 copyright = "2019-2022, Pyodide contributors and Mozilla"
22 
23 # -- General configuration ---------------------------------------------------
24 
25 # If your documentation needs a minimal Sphinx version, state it here.
26 #
27 # needs_sphinx = '1.0'
28 
29 extensions = [
30     "sphinx.ext.autodoc",
31     "sphinx.ext.autosummary",
32     "sphinx.ext.intersphinx",
33     "sphinx.ext.napoleon",
34     "myst_parser",
35     "sphinx_js",
36     "sphinx_click",
37     "autodocsumm",
38     "sphinx_pyodide",
39     "sphinx_argparse_cli",
40     "versionwarning.extension",
41     "sphinx_issues",
42     "sphinx_autodoc_typehints",
43     "sphinx_design",  # Used for tabs in building-from-sources.md
44 ]
45 
46 
47 myst_enable_extensions = ["substitution"]
48 
49 js_language = "typescript"
50 jsdoc_config_path = "../src/js/tsconfig.json"
51 root_for_relative_js_paths = "../src/"
52 issues_github_path = "pyodide/pyodide"
53 
54 versionwarning_messages = {
55     "latest": (
56         "This is the development version of the documentation. "
57         'See <a href="https://pyodide.org/">here</a> for latest stable '
58         "documentation. Please do not use Pyodide with non "
59         "versioned (`dev`) URLs from the CDN for deployed applications!"
60     )
61 }
62 versionwarning_body_selector = "#main-content > div"
63 
64 autosummary_generate = True
65 autodoc_default_flags = ["members", "inherited-members"]
66 
67 intersphinx_mapping = {
68     "python": ("https://docs.python.org/3.10", None),
69     "micropip": (f"https://micropip.pyodide.org/en/v{micropip.__version__}/", None),
70     "numpy": ("https://numpy.org/doc/stable/", None),
71 }
72 
73 # Add modules to be mocked.
74 mock_modules = ["tomli"]
75 
76 # Add any paths that contain templates here, relative to this directory.
77 templates_path = ["_templates"]
78 
79 # The suffix(es) of source filenames.
80 source_suffix = [".rst", ".md"]
81 
82 # The master toctree document.
83 master_doc = "index"
84 
85 # List of patterns, relative to source directory, that match files and
86 # directories to ignore when looking for source files.
87 exclude_patterns = [
88     "_build",
89     "Thumbs.db",
90     ".DS_Store",
91     "README.md",
92     "sphinx_pyodide",
93     ".*",
94 ]
95 
96 # The name of the Pygments (syntax highlighting) style to use.
97 pygments_style = None
98 
99 # -- Options for HTML output -------------------------------------------------
100 
101 # The theme to use for HTML and HTML Help pages.  See the documentation for
102 # a list of builtin themes.
103 #
104 html_theme = "sphinx_book_theme"
105 html_logo = "_static/img/pyodide-logo.png"
106 
107 # theme-specific options
108 html_theme_options: dict[str, Any] = {}
109 
110 # paths that contain custom static files (such as style sheets)
111 html_static_path = ["_static"]
112 
113 
114 html_css_files = [
115     "css/pyodide.css",
116 ]
117 
118 # Custom sidebar templates, must be a dictionary that maps document names
119 # to template names.
120 # html_sidebars = {}
121 
122 # -- Options for HTMLHelp output ---------------------------------------------
123 
124 # Output file base name for HTML help builder.
125 htmlhelp_basename = "Pyodidedoc"
126 
127 # A list of files that should not be packed into the epub file.
128 epub_exclude_files = ["search.html"]
129 
130 # Try not to cause side effects if we are imported incidentally.
131 
132 IN_SPHINX = "sphinx" in sys.modules and hasattr(sys.modules["sphinx"], "application")
133 IN_READTHEDOCS = "READTHEDOCS" in os.environ
134 
135 
136 base_dir = Path(__file__).resolve().parent.parent
137 extra_sys_path_dirs = [
138     str(base_dir),
139     str(base_dir / "pyodide-build"),
140     str(base_dir / "src/py"),
141     str(base_dir / "packages/micropip/src"),
142 ]
143 
144 
145 if IN_SPHINX:
146     # sphinx_pyodide is imported before setup() is called because it's a sphinx
147     # extension, so we need it to be on the path early. Everything else can be
148     # added to the path in setup().
149     #
150     # TODO: pip install -e sphinx-pyodide instead.
151     sys.path = [str(base_dir / "docs/sphinx_pyodide")] + sys.path
152 
153 
154 def patch_docs_argspec():
155     import builtins
156 
157     from sphinx_pyodide.util import docs_argspec
158 
159     # override docs_argspec, _pyodide.docs_argspec will read this value back.
160     # Must do this before importing pyodide!
161     setattr(builtins, "--docs_argspec--", docs_argspec)
162 
163 
164 def patch_inspect():
165     # Monkey patch for python3.11 incompatible code
166     import inspect
167 
168     if not hasattr(inspect, "getargspec"):
169         inspect.getargspec = inspect.getfullargspec  # type: ignore[assignment]
170 
171 
172 def prevent_parens_after_js_class_xrefs():
173     from sphinx.domains.javascript import JavaScriptDomain, JSXRefRole
174 
175     JavaScriptDomain.roles["class"] = JSXRefRole()
176 
177 
178 def apply_patches():
179     patch_docs_argspec()
180     patch_inspect()
181     prevent_parens_after_js_class_xrefs()
182 
183 
184 def calculate_pyodide_version(app):
185     import pyodide
186 
187     config = app.config
188 
189     # The full version, including alpha/beta/rc tags.
190     config.release = config.version = version = pyodide.__version__
191 
192     if ".dev" in version or os.environ.get("READTHEDOCS_VERSION") == "latest":
193         CDN_URL = "https://cdn.jsdelivr.net/pyodide/dev/full/"
194     else:
195         CDN_URL = f"https://cdn.jsdelivr.net/pyodide/v{version}/full/"
196 
197     app.config.CDN_URL = CDN_URL
198     app.config.html_title = f"Version {version}"
199 
200     app.config.global_replacements = {
201         "{{PYODIDE_CDN_URL}}": CDN_URL,
202         "{{VERSION}}": version,
203     }
204 
205 
206 def write_console_html(app):
207     # Make console.html file
208     env = {"PYODIDE_BASE_URL": app.config.CDN_URL}
209     os.makedirs(app.outdir, exist_ok=True)
210     os.makedirs("../dist", exist_ok=True)
211     res = subprocess.check_output(
212         ["make", "-C", "..", "dist/console.html"],
213         env=env,
214         stderr=subprocess.STDOUT,
215         encoding="utf-8",
216     )
217     print(res)
218 
219     # insert the Plausible analytics script to console.html
220     console_html_lines = (
221         Path("../dist/console.html").read_text().splitlines(keepends=True)
222     )
223     for idx, line in enumerate(list(console_html_lines)):
224         if 'pyodide.js">' in line:
225             # insert the analytics script after the `pyodide.js` script
226             console_html_lines.insert(
227                 idx,
228                 '<script defer data-domain="pyodide.org" src="https://plausible.io/js/plausible.js"></script>\n',
229             )
230             break
231     else:
232         raise ValueError("Could not find pyodide.js in the <head> section")
233     output_path = Path(app.outdir) / "console.html"
234     output_path.write_text("".join(console_html_lines))
235 
236 
237 def ensure_typedoc_on_path():
238     if shutil.which("typedoc"):
239         return
240     os.environ["PATH"] += f':{str(Path("../src/js/node_modules/.bin").resolve())}'
241     print(os.environ["PATH"])
242     if shutil.which("typedoc"):
243         return
244     if IN_READTHEDOCS:
245         subprocess.run(["npm", "ci"], cwd="../src/js")
246     if shutil.which("typedoc"):
247         return
248     raise Exception(
249         "Before building the Pyodide docs you must run 'npm install' in 'src/js'."
250     )
251 
252 
253 def create_generated_typescript_files(app):
254     shutil.copy("../src/core/pyproxy.ts", "../src/js/pyproxy.gen.ts")
255     shutil.copy("../src/core/error_handling.ts", "../src/js/error_handling.gen.ts")
256     app.config.js_source_path = [str(x) for x in Path("../src/js").glob("*.ts")]
257 
258     def remove_pyproxy_gen_ts():
259         Path("../src/js/pyproxy.gen.ts").unlink(missing_ok=True)
260 
261     atexit.register(remove_pyproxy_gen_ts)
262 
263 
264 def prune_webloop_docs():
265     # Prevent API docs for webloop methods: they are the same as for base event loop
266     # and it clutters api docs too much
267     from sphinx_pyodide.util import delete_attrs
268 
269     import pyodide.console
270     import pyodide.webloop
271 
272     delete_attrs(pyodide.webloop.WebLoop)
273     delete_attrs(pyodide.webloop.WebLoopPolicy)
274     delete_attrs(pyodide.console.PyodideConsole)
275 
276     for module in mock_modules:
277         sys.modules[module] = mock.Mock()
278 
279 
280 def prune_jsproxy_constructor_docs():
281     from pyodide.ffi import JsProxy
282 
283     del JsProxy.__new__
284 
285 
286 def prune_docs():
287     prune_webloop_docs()
288     prune_jsproxy_constructor_docs()
289 
290 
291 # https://github.com/sphinx-doc/sphinx/issues/4054
292 def global_replace(app, docname, source):
293     result = source[0]
294     for key in app.config.global_replacements:
295         result = result.replace(key, app.config.global_replacements[key])
296     source[0] = result
297 
298 
299 always_document_param_types = True
300 
301 
302 def typehints_formatter(annotation, config):
303     """Adjust the rendering of various types that sphinx_autodoc_typehints mishandles"""
304     from sphinx_autodoc_typehints import (
305         get_annotation_class_name,
306         get_annotation_module,
307     )
308 
309     try:
310         module = get_annotation_module(annotation)
311         class_name = get_annotation_class_name(annotation, module)
312     except ValueError:
313         return None
314     full_name = f"{module}.{class_name}"
315     if full_name == "typing.TypeVar":
316         # The way sphinx-autodoc-typehints renders TypeVar is too noisy for my
317         # taste
318         return f"``{annotation.__name__}``"
319     if full_name == "ast.Module":
320         return "`Module <https://docs.python.org/3/library/ast.html#module-ast>`_"
321     return None
322 
323 
324 def setup(app):
325     sys.path = extra_sys_path_dirs + sys.path
326     app.add_config_value("global_replacements", {}, True)
327     app.add_config_value("CDN_URL", "", True)
328     app.connect("source-read", global_replace)
329 
330     apply_patches()
331     calculate_pyodide_version(app)
332     ensure_typedoc_on_path()
333     create_generated_typescript_files(app)
334     write_console_html(app)
335     prune_docs()
336
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/docs/conf.py b/docs/conf.py
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -37,7 +37,6 @@
     "autodocsumm",
     "sphinx_pyodide",
     "sphinx_argparse_cli",
-    "versionwarning.extension",
     "sphinx_issues",
     "sphinx_autodoc_typehints",
     "sphinx_design",  # Used for tabs in building-from-sources.md
@@ -51,15 +50,12 @@
 root_for_relative_js_paths = "../src/"
 issues_github_path = "pyodide/pyodide"
 
-versionwarning_messages = {
-    "latest": (
-        "This is the development version of the documentation. "
-        'See <a href="https://pyodide.org/">here</a> for latest stable '
-        "documentation. Please do not use Pyodide with non "
-        "versioned (`dev`) URLs from the CDN for deployed applications!"
-    )
-}
-versionwarning_body_selector = "#main-content > div"
+versionwarning_message = (
+    "This is the development version of the documentation. "
+    'See <a href="https://pyodide.org/">here</a> for latest stable '
+    "documentation. Please do not use Pyodide with non "
+    "versioned (`dev`) URLs from the CDN for deployed applications!"
+)
 
 autosummary_generate = True
 autodoc_default_flags = ["members", "inherited-members"]
@@ -105,7 +101,9 @@
 html_logo = "_static/img/pyodide-logo.png"
 
 # theme-specific options
-html_theme_options: dict[str, Any] = {}
+html_theme_options: dict[str, Any] = {
+    "announcement": "",
+}
 
 # paths that contain custom static files (such as style sheets)
 html_static_path = ["_static"]
@@ -131,6 +129,9 @@
 
 IN_SPHINX = "sphinx" in sys.modules and hasattr(sys.modules["sphinx"], "application")
 IN_READTHEDOCS = "READTHEDOCS" in os.environ
+IN_READTHEDOCS_LATEST = (
+    IN_READTHEDOCS and os.environ.get("READTHEDOCS_VERSION") == "latest"
+)
 
 
 base_dir = Path(__file__).resolve().parent.parent
@@ -203,6 +204,12 @@
     }
 
 
+def set_announcement_message():
+    html_theme_options["announcement"] = (
+        versionwarning_message if IN_READTHEDOCS_LATEST else ""
+    )
+
+
 def write_console_html(app):
     # Make console.html file
     env = {"PYODIDE_BASE_URL": app.config.CDN_URL}
@@ -327,6 +334,7 @@
     app.add_config_value("CDN_URL", "", True)
     app.connect("source-read", global_replace)
 
+    set_announcement_message()
     apply_patches()
     calculate_pyodide_version(app)
     ensure_typedoc_on_path()

{"golden_diff": "diff --git a/docs/conf.py b/docs/conf.py\n--- a/docs/conf.py\n+++ b/docs/conf.py\n@@ -37,7 +37,6 @@\n     \"autodocsumm\",\n     \"sphinx_pyodide\",\n     \"sphinx_argparse_cli\",\n-    \"versionwarning.extension\",\n     \"sphinx_issues\",\n     \"sphinx_autodoc_typehints\",\n     \"sphinx_design\",  # Used for tabs in building-from-sources.md\n@@ -51,15 +50,12 @@\n root_for_relative_js_paths = \"../src/\"\n issues_github_path = \"pyodide/pyodide\"\n \n-versionwarning_messages = {\n-    \"latest\": (\n-        \"This is the development version of the documentation. \"\n-        'See <a href=\"https://pyodide.org/\">here</a> for latest stable '\n-        \"documentation. Please do not use Pyodide with non \"\n-        \"versioned (`dev`) URLs from the CDN for deployed applications!\"\n-    )\n-}\n-versionwarning_body_selector = \"#main-content > div\"\n+versionwarning_message = (\n+    \"This is the development version of the documentation. \"\n+    'See <a href=\"https://pyodide.org/\">here</a> for latest stable '\n+    \"documentation. Please do not use Pyodide with non \"\n+    \"versioned (`dev`) URLs from the CDN for deployed applications!\"\n+)\n \n autosummary_generate = True\n autodoc_default_flags = [\"members\", \"inherited-members\"]\n@@ -105,7 +101,9 @@\n html_logo = \"_static/img/pyodide-logo.png\"\n \n # theme-specific options\n-html_theme_options: dict[str, Any] = {}\n+html_theme_options: dict[str, Any] = {\n+    \"announcement\": \"\",\n+}\n \n # paths that contain custom static files (such as style sheets)\n html_static_path = [\"_static\"]\n@@ -131,6 +129,9 @@\n \n IN_SPHINX = \"sphinx\" in sys.modules and hasattr(sys.modules[\"sphinx\"], \"application\")\n IN_READTHEDOCS = \"READTHEDOCS\" in os.environ\n+IN_READTHEDOCS_LATEST = (\n+    IN_READTHEDOCS and os.environ.get(\"READTHEDOCS_VERSION\") == \"latest\"\n+)\n \n \n base_dir = Path(__file__).resolve().parent.parent\n@@ -203,6 +204,12 @@\n     }\n \n \n+def set_announcement_message():\n+    html_theme_options[\"announcement\"] = (\n+        versionwarning_message if IN_READTHEDOCS_LATEST else \"\"\n+    )\n+\n+\n def write_console_html(app):\n     # Make console.html file\n     env = {\"PYODIDE_BASE_URL\": app.config.CDN_URL}\n@@ -327,6 +334,7 @@\n     app.add_config_value(\"CDN_URL\", \"\", True)\n     app.connect(\"source-read\", global_replace)\n \n+    set_announcement_message()\n     apply_patches()\n     calculate_pyodide_version(app)\n     ensure_typedoc_on_path()\n", "issue": "CSS broken in latest docs\n## \ud83d\udc1b Bug\r\n\r\n![image](https://user-images.githubusercontent.com/24893111/214972488-e914fb00-d431-4354-9bdd-bf4b67f76516.png)\r\n\r\nIt seems like the versionwarning banner is not displayed correctly in latest docs.\r\n\n", "before_files": [{"content": "# Configuration file for the Sphinx documentation builder.\n\n# -- Path setup --------------------------------------------------------------\n\nimport atexit\nimport os\nimport shutil\nimport subprocess\nimport sys\nfrom pathlib import Path\nfrom typing import Any\nfrom unittest import mock\n\nimport micropip\n\npanels_add_bootstrap_css = False\n\n# -- Project information -----------------------------------------------------\n\nproject = \"Pyodide\"\ncopyright = \"2019-2022, Pyodide contributors and Mozilla\"\n\n# -- General configuration ---------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#\n# needs_sphinx = '1.0'\n\nextensions = [\n    \"sphinx.ext.autodoc\",\n    \"sphinx.ext.autosummary\",\n    \"sphinx.ext.intersphinx\",\n    \"sphinx.ext.napoleon\",\n    \"myst_parser\",\n    \"sphinx_js\",\n    \"sphinx_click\",\n    \"autodocsumm\",\n    \"sphinx_pyodide\",\n    \"sphinx_argparse_cli\",\n    \"versionwarning.extension\",\n    \"sphinx_issues\",\n    \"sphinx_autodoc_typehints\",\n    \"sphinx_design\",  # Used for tabs in building-from-sources.md\n]\n\n\nmyst_enable_extensions = [\"substitution\"]\n\njs_language = \"typescript\"\njsdoc_config_path = \"../src/js/tsconfig.json\"\nroot_for_relative_js_paths = \"../src/\"\nissues_github_path = \"pyodide/pyodide\"\n\nversionwarning_messages = {\n    \"latest\": (\n        \"This is the development version of the documentation. \"\n        'See <a href=\"https://pyodide.org/\">here</a> for latest stable '\n        \"documentation. Please do not use Pyodide with non \"\n        \"versioned (`dev`) URLs from the CDN for deployed applications!\"\n    )\n}\nversionwarning_body_selector = \"#main-content > div\"\n\nautosummary_generate = True\nautodoc_default_flags = [\"members\", \"inherited-members\"]\n\nintersphinx_mapping = {\n    \"python\": (\"https://docs.python.org/3.10\", None),\n    \"micropip\": (f\"https://micropip.pyodide.org/en/v{micropip.__version__}/\", None),\n    \"numpy\": (\"https://numpy.org/doc/stable/\", None),\n}\n\n# Add modules to be mocked.\nmock_modules = [\"tomli\"]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = [\"_templates\"]\n\n# The suffix(es) of source filenames.\nsource_suffix = [\".rst\", \".md\"]\n\n# The master toctree document.\nmaster_doc = \"index\"\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\nexclude_patterns = [\n    \"_build\",\n    \"Thumbs.db\",\n    \".DS_Store\",\n    \"README.md\",\n    \"sphinx_pyodide\",\n    \".*\",\n]\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = None\n\n# -- Options for HTML output -------------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\nhtml_theme = \"sphinx_book_theme\"\nhtml_logo = \"_static/img/pyodide-logo.png\"\n\n# theme-specific options\nhtml_theme_options: dict[str, Any] = {}\n\n# paths that contain custom static files (such as style sheets)\nhtml_static_path = [\"_static\"]\n\n\nhtml_css_files = [\n    \"css/pyodide.css\",\n]\n\n# Custom sidebar templates, must be a dictionary that maps document names\n# to template names.\n# html_sidebars = {}\n\n# -- Options for HTMLHelp output ---------------------------------------------\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = \"Pyodidedoc\"\n\n# A list of files that should not be packed into the epub file.\nepub_exclude_files = [\"search.html\"]\n\n# Try not to cause side effects if we are imported incidentally.\n\nIN_SPHINX = \"sphinx\" in sys.modules and hasattr(sys.modules[\"sphinx\"], \"application\")\nIN_READTHEDOCS = \"READTHEDOCS\" in os.environ\n\n\nbase_dir = Path(__file__).resolve().parent.parent\nextra_sys_path_dirs = [\n    str(base_dir),\n    str(base_dir / \"pyodide-build\"),\n    str(base_dir / \"src/py\"),\n    str(base_dir / \"packages/micropip/src\"),\n]\n\n\nif IN_SPHINX:\n    # sphinx_pyodide is imported before setup() is called because it's a sphinx\n    # extension, so we need it to be on the path early. Everything else can be\n    # added to the path in setup().\n    #\n    # TODO: pip install -e sphinx-pyodide instead.\n    sys.path = [str(base_dir / \"docs/sphinx_pyodide\")] + sys.path\n\n\ndef patch_docs_argspec():\n    import builtins\n\n    from sphinx_pyodide.util import docs_argspec\n\n    # override docs_argspec, _pyodide.docs_argspec will read this value back.\n    # Must do this before importing pyodide!\n    setattr(builtins, \"--docs_argspec--\", docs_argspec)\n\n\ndef patch_inspect():\n    # Monkey patch for python3.11 incompatible code\n    import inspect\n\n    if not hasattr(inspect, \"getargspec\"):\n        inspect.getargspec = inspect.getfullargspec  # type: ignore[assignment]\n\n\ndef prevent_parens_after_js_class_xrefs():\n    from sphinx.domains.javascript import JavaScriptDomain, JSXRefRole\n\n    JavaScriptDomain.roles[\"class\"] = JSXRefRole()\n\n\ndef apply_patches():\n    patch_docs_argspec()\n    patch_inspect()\n    prevent_parens_after_js_class_xrefs()\n\n\ndef calculate_pyodide_version(app):\n    import pyodide\n\n    config = app.config\n\n    # The full version, including alpha/beta/rc tags.\n    config.release = config.version = version = pyodide.__version__\n\n    if \".dev\" in version or os.environ.get(\"READTHEDOCS_VERSION\") == \"latest\":\n        CDN_URL = \"https://cdn.jsdelivr.net/pyodide/dev/full/\"\n    else:\n        CDN_URL = f\"https://cdn.jsdelivr.net/pyodide/v{version}/full/\"\n\n    app.config.CDN_URL = CDN_URL\n    app.config.html_title = f\"Version {version}\"\n\n    app.config.global_replacements = {\n        \"{{PYODIDE_CDN_URL}}\": CDN_URL,\n        \"{{VERSION}}\": version,\n    }\n\n\ndef write_console_html(app):\n    # Make console.html file\n    env = {\"PYODIDE_BASE_URL\": app.config.CDN_URL}\n    os.makedirs(app.outdir, exist_ok=True)\n    os.makedirs(\"../dist\", exist_ok=True)\n    res = subprocess.check_output(\n        [\"make\", \"-C\", \"..\", \"dist/console.html\"],\n        env=env,\n        stderr=subprocess.STDOUT,\n        encoding=\"utf-8\",\n    )\n    print(res)\n\n    # insert the Plausible analytics script to console.html\n    console_html_lines = (\n        Path(\"../dist/console.html\").read_text().splitlines(keepends=True)\n    )\n    for idx, line in enumerate(list(console_html_lines)):\n        if 'pyodide.js\">' in line:\n            # insert the analytics script after the `pyodide.js` script\n            console_html_lines.insert(\n                idx,\n                '<script defer data-domain=\"pyodide.org\" src=\"https://plausible.io/js/plausible.js\"></script>\\n',\n            )\n            break\n    else:\n        raise ValueError(\"Could not find pyodide.js in the <head> section\")\n    output_path = Path(app.outdir) / \"console.html\"\n    output_path.write_text(\"\".join(console_html_lines))\n\n\ndef ensure_typedoc_on_path():\n    if shutil.which(\"typedoc\"):\n        return\n    os.environ[\"PATH\"] += f':{str(Path(\"../src/js/node_modules/.bin\").resolve())}'\n    print(os.environ[\"PATH\"])\n    if shutil.which(\"typedoc\"):\n        return\n    if IN_READTHEDOCS:\n        subprocess.run([\"npm\", \"ci\"], cwd=\"../src/js\")\n    if shutil.which(\"typedoc\"):\n        return\n    raise Exception(\n        \"Before building the Pyodide docs you must run 'npm install' in 'src/js'.\"\n    )\n\n\ndef create_generated_typescript_files(app):\n    shutil.copy(\"../src/core/pyproxy.ts\", \"../src/js/pyproxy.gen.ts\")\n    shutil.copy(\"../src/core/error_handling.ts\", \"../src/js/error_handling.gen.ts\")\n    app.config.js_source_path = [str(x) for x in Path(\"../src/js\").glob(\"*.ts\")]\n\n    def remove_pyproxy_gen_ts():\n        Path(\"../src/js/pyproxy.gen.ts\").unlink(missing_ok=True)\n\n    atexit.register(remove_pyproxy_gen_ts)\n\n\ndef prune_webloop_docs():\n    # Prevent API docs for webloop methods: they are the same as for base event loop\n    # and it clutters api docs too much\n    from sphinx_pyodide.util import delete_attrs\n\n    import pyodide.console\n    import pyodide.webloop\n\n    delete_attrs(pyodide.webloop.WebLoop)\n    delete_attrs(pyodide.webloop.WebLoopPolicy)\n    delete_attrs(pyodide.console.PyodideConsole)\n\n    for module in mock_modules:\n        sys.modules[module] = mock.Mock()\n\n\ndef prune_jsproxy_constructor_docs():\n    from pyodide.ffi import JsProxy\n\n    del JsProxy.__new__\n\n\ndef prune_docs():\n    prune_webloop_docs()\n    prune_jsproxy_constructor_docs()\n\n\n# https://github.com/sphinx-doc/sphinx/issues/4054\ndef global_replace(app, docname, source):\n    result = source[0]\n    for key in app.config.global_replacements:\n        result = result.replace(key, app.config.global_replacements[key])\n    source[0] = result\n\n\nalways_document_param_types = True\n\n\ndef typehints_formatter(annotation, config):\n    \"\"\"Adjust the rendering of various types that sphinx_autodoc_typehints mishandles\"\"\"\n    from sphinx_autodoc_typehints import (\n        get_annotation_class_name,\n        get_annotation_module,\n    )\n\n    try:\n        module = get_annotation_module(annotation)\n        class_name = get_annotation_class_name(annotation, module)\n    except ValueError:\n        return None\n    full_name = f\"{module}.{class_name}\"\n    if full_name == \"typing.TypeVar\":\n        # The way sphinx-autodoc-typehints renders TypeVar is too noisy for my\n        # taste\n        return f\"``{annotation.__name__}``\"\n    if full_name == \"ast.Module\":\n        return \"`Module <https://docs.python.org/3/library/ast.html#module-ast>`_\"\n    return None\n\n\ndef setup(app):\n    sys.path = extra_sys_path_dirs + sys.path\n    app.add_config_value(\"global_replacements\", {}, True)\n    app.add_config_value(\"CDN_URL\", \"\", True)\n    app.connect(\"source-read\", global_replace)\n\n    apply_patches()\n    calculate_pyodide_version(app)\n    ensure_typedoc_on_path()\n    create_generated_typescript_files(app)\n    write_console_html(app)\n    prune_docs()\n", "path": "docs/conf.py"}], "after_files": [{"content": "# Configuration file for the Sphinx documentation builder.\n\n# -- Path setup --------------------------------------------------------------\n\nimport atexit\nimport os\nimport shutil\nimport subprocess\nimport sys\nfrom pathlib import Path\nfrom typing import Any\nfrom unittest import mock\n\nimport micropip\n\npanels_add_bootstrap_css = False\n\n# -- Project information -----------------------------------------------------\n\nproject = \"Pyodide\"\ncopyright = \"2019-2022, Pyodide contributors and Mozilla\"\n\n# -- General configuration ---------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#\n# needs_sphinx = '1.0'\n\nextensions = [\n    \"sphinx.ext.autodoc\",\n    \"sphinx.ext.autosummary\",\n    \"sphinx.ext.intersphinx\",\n    \"sphinx.ext.napoleon\",\n    \"myst_parser\",\n    \"sphinx_js\",\n    \"sphinx_click\",\n    \"autodocsumm\",\n    \"sphinx_pyodide\",\n    \"sphinx_argparse_cli\",\n    \"sphinx_issues\",\n    \"sphinx_autodoc_typehints\",\n    \"sphinx_design\",  # Used for tabs in building-from-sources.md\n]\n\n\nmyst_enable_extensions = [\"substitution\"]\n\njs_language = \"typescript\"\njsdoc_config_path = \"../src/js/tsconfig.json\"\nroot_for_relative_js_paths = \"../src/\"\nissues_github_path = \"pyodide/pyodide\"\n\nversionwarning_message = (\n    \"This is the development version of the documentation. \"\n    'See <a href=\"https://pyodide.org/\">here</a> for latest stable '\n    \"documentation. Please do not use Pyodide with non \"\n    \"versioned (`dev`) URLs from the CDN for deployed applications!\"\n)\n\nautosummary_generate = True\nautodoc_default_flags = [\"members\", \"inherited-members\"]\n\nintersphinx_mapping = {\n    \"python\": (\"https://docs.python.org/3.10\", None),\n    \"micropip\": (f\"https://micropip.pyodide.org/en/v{micropip.__version__}/\", None),\n    \"numpy\": (\"https://numpy.org/doc/stable/\", None),\n}\n\n# Add modules to be mocked.\nmock_modules = [\"tomli\"]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = [\"_templates\"]\n\n# The suffix(es) of source filenames.\nsource_suffix = [\".rst\", \".md\"]\n\n# The master toctree document.\nmaster_doc = \"index\"\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\nexclude_patterns = [\n    \"_build\",\n    \"Thumbs.db\",\n    \".DS_Store\",\n    \"README.md\",\n    \"sphinx_pyodide\",\n    \".*\",\n]\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = None\n\n# -- Options for HTML output -------------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\nhtml_theme = \"sphinx_book_theme\"\nhtml_logo = \"_static/img/pyodide-logo.png\"\n\n# theme-specific options\nhtml_theme_options: dict[str, Any] = {\n    \"announcement\": \"\",\n}\n\n# paths that contain custom static files (such as style sheets)\nhtml_static_path = [\"_static\"]\n\n\nhtml_css_files = [\n    \"css/pyodide.css\",\n]\n\n# Custom sidebar templates, must be a dictionary that maps document names\n# to template names.\n# html_sidebars = {}\n\n# -- Options for HTMLHelp output ---------------------------------------------\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = \"Pyodidedoc\"\n\n# A list of files that should not be packed into the epub file.\nepub_exclude_files = [\"search.html\"]\n\n# Try not to cause side effects if we are imported incidentally.\n\nIN_SPHINX = \"sphinx\" in sys.modules and hasattr(sys.modules[\"sphinx\"], \"application\")\nIN_READTHEDOCS = \"READTHEDOCS\" in os.environ\nIN_READTHEDOCS_LATEST = (\n    IN_READTHEDOCS and os.environ.get(\"READTHEDOCS_VERSION\") == \"latest\"\n)\n\n\nbase_dir = Path(__file__).resolve().parent.parent\nextra_sys_path_dirs = [\n    str(base_dir),\n    str(base_dir / \"pyodide-build\"),\n    str(base_dir / \"src/py\"),\n    str(base_dir / \"packages/micropip/src\"),\n]\n\n\nif IN_SPHINX:\n    # sphinx_pyodide is imported before setup() is called because it's a sphinx\n    # extension, so we need it to be on the path early. Everything else can be\n    # added to the path in setup().\n    #\n    # TODO: pip install -e sphinx-pyodide instead.\n    sys.path = [str(base_dir / \"docs/sphinx_pyodide\")] + sys.path\n\n\ndef patch_docs_argspec():\n    import builtins\n\n    from sphinx_pyodide.util import docs_argspec\n\n    # override docs_argspec, _pyodide.docs_argspec will read this value back.\n    # Must do this before importing pyodide!\n    setattr(builtins, \"--docs_argspec--\", docs_argspec)\n\n\ndef patch_inspect():\n    # Monkey patch for python3.11 incompatible code\n    import inspect\n\n    if not hasattr(inspect, \"getargspec\"):\n        inspect.getargspec = inspect.getfullargspec  # type: ignore[assignment]\n\n\ndef prevent_parens_after_js_class_xrefs():\n    from sphinx.domains.javascript import JavaScriptDomain, JSXRefRole\n\n    JavaScriptDomain.roles[\"class\"] = JSXRefRole()\n\n\ndef apply_patches():\n    patch_docs_argspec()\n    patch_inspect()\n    prevent_parens_after_js_class_xrefs()\n\n\ndef calculate_pyodide_version(app):\n    import pyodide\n\n    config = app.config\n\n    # The full version, including alpha/beta/rc tags.\n    config.release = config.version = version = pyodide.__version__\n\n    if \".dev\" in version or os.environ.get(\"READTHEDOCS_VERSION\") == \"latest\":\n        CDN_URL = \"https://cdn.jsdelivr.net/pyodide/dev/full/\"\n    else:\n        CDN_URL = f\"https://cdn.jsdelivr.net/pyodide/v{version}/full/\"\n\n    app.config.CDN_URL = CDN_URL\n    app.config.html_title = f\"Version {version}\"\n\n    app.config.global_replacements = {\n        \"{{PYODIDE_CDN_URL}}\": CDN_URL,\n        \"{{VERSION}}\": version,\n    }\n\n\ndef set_announcement_message():\n    html_theme_options[\"announcement\"] = (\n        versionwarning_message if IN_READTHEDOCS_LATEST else \"\"\n    )\n\n\ndef write_console_html(app):\n    # Make console.html file\n    env = {\"PYODIDE_BASE_URL\": app.config.CDN_URL}\n    os.makedirs(app.outdir, exist_ok=True)\n    os.makedirs(\"../dist\", exist_ok=True)\n    res = subprocess.check_output(\n        [\"make\", \"-C\", \"..\", \"dist/console.html\"],\n        env=env,\n        stderr=subprocess.STDOUT,\n        encoding=\"utf-8\",\n    )\n    print(res)\n\n    # insert the Plausible analytics script to console.html\n    console_html_lines = (\n        Path(\"../dist/console.html\").read_text().splitlines(keepends=True)\n    )\n    for idx, line in enumerate(list(console_html_lines)):\n        if 'pyodide.js\">' in line:\n            # insert the analytics script after the `pyodide.js` script\n            console_html_lines.insert(\n                idx,\n                '<script defer data-domain=\"pyodide.org\" src=\"https://plausible.io/js/plausible.js\"></script>\\n',\n            )\n            break\n    else:\n        raise ValueError(\"Could not find pyodide.js in the <head> section\")\n    output_path = Path(app.outdir) / \"console.html\"\n    output_path.write_text(\"\".join(console_html_lines))\n\n\ndef ensure_typedoc_on_path():\n    if shutil.which(\"typedoc\"):\n        return\n    os.environ[\"PATH\"] += f':{str(Path(\"../src/js/node_modules/.bin\").resolve())}'\n    print(os.environ[\"PATH\"])\n    if shutil.which(\"typedoc\"):\n        return\n    if IN_READTHEDOCS:\n        subprocess.run([\"npm\", \"ci\"], cwd=\"../src/js\")\n    if shutil.which(\"typedoc\"):\n        return\n    raise Exception(\n        \"Before building the Pyodide docs you must run 'npm install' in 'src/js'.\"\n    )\n\n\ndef create_generated_typescript_files(app):\n    shutil.copy(\"../src/core/pyproxy.ts\", \"../src/js/pyproxy.gen.ts\")\n    shutil.copy(\"../src/core/error_handling.ts\", \"../src/js/error_handling.gen.ts\")\n    app.config.js_source_path = [str(x) for x in Path(\"../src/js\").glob(\"*.ts\")]\n\n    def remove_pyproxy_gen_ts():\n        Path(\"../src/js/pyproxy.gen.ts\").unlink(missing_ok=True)\n\n    atexit.register(remove_pyproxy_gen_ts)\n\n\ndef prune_webloop_docs():\n    # Prevent API docs for webloop methods: they are the same as for base event loop\n    # and it clutters api docs too much\n    from sphinx_pyodide.util import delete_attrs\n\n    import pyodide.console\n    import pyodide.webloop\n\n    delete_attrs(pyodide.webloop.WebLoop)\n    delete_attrs(pyodide.webloop.WebLoopPolicy)\n    delete_attrs(pyodide.console.PyodideConsole)\n\n    for module in mock_modules:\n        sys.modules[module] = mock.Mock()\n\n\ndef prune_jsproxy_constructor_docs():\n    from pyodide.ffi import JsProxy\n\n    del JsProxy.__new__\n\n\ndef prune_docs():\n    prune_webloop_docs()\n    prune_jsproxy_constructor_docs()\n\n\n# https://github.com/sphinx-doc/sphinx/issues/4054\ndef global_replace(app, docname, source):\n    result = source[0]\n    for key in app.config.global_replacements:\n        result = result.replace(key, app.config.global_replacements[key])\n    source[0] = result\n\n\nalways_document_param_types = True\n\n\ndef typehints_formatter(annotation, config):\n    \"\"\"Adjust the rendering of various types that sphinx_autodoc_typehints mishandles\"\"\"\n    from sphinx_autodoc_typehints import (\n        get_annotation_class_name,\n        get_annotation_module,\n    )\n\n    try:\n        module = get_annotation_module(annotation)\n        class_name = get_annotation_class_name(annotation, module)\n    except ValueError:\n        return None\n    full_name = f\"{module}.{class_name}\"\n    if full_name == \"typing.TypeVar\":\n        # The way sphinx-autodoc-typehints renders TypeVar is too noisy for my\n        # taste\n        return f\"``{annotation.__name__}``\"\n    if full_name == \"ast.Module\":\n        return \"`Module <https://docs.python.org/3/library/ast.html#module-ast>`_\"\n    return None\n\n\ndef setup(app):\n    sys.path = extra_sys_path_dirs + sys.path\n    app.add_config_value(\"global_replacements\", {}, True)\n    app.add_config_value(\"CDN_URL\", \"\", True)\n    app.connect(\"source-read\", global_replace)\n\n    set_announcement_message()\n    apply_patches()\n    calculate_pyodide_version(app)\n    ensure_typedoc_on_path()\n    create_generated_typescript_files(app)\n    write_console_html(app)\n    prune_docs()\n", "path": "docs/conf.py"}]}