|
12 | 12 |
|
13 | 13 | import os |
14 | 14 | import sys |
| 15 | +import shutil |
15 | 16 |
|
| 17 | +import flit |
16 | 18 |
|
17 | 19 | ROOT_DIR = os.path.abspath(os.path.join(__file__, "..", "..")) |
18 | 20 | sys.path.insert(0, ROOT_DIR) |
19 | 21 |
|
20 | 22 | os.environ["RENDERCANVAS_FORCE_OFFSCREEN"] = "true" |
21 | 23 |
|
22 | 24 |
|
23 | | -# Load wglibu so autodoc can query docstrings |
| 25 | +# Load wgpu so autodoc can query docstrings |
24 | 26 | import rendercanvas # noqa: E402 |
25 | | -import rendercanvas.stub # noqa: E402 - we use the stub backend to generate doccs |
26 | | -import rendercanvas._context # noqa: E402 - we use the ContexInterface to generate doccs |
| 27 | +import rendercanvas.stub # noqa: E402 - we use the stub backend to generate docs |
| 28 | +import rendercanvas._context # noqa: E402 - we use the ContextInterface to generate docs |
27 | 29 | import rendercanvas.utils.bitmappresentadapter # noqa: E402 |
28 | 30 |
|
29 | 31 | # -- Project information ----------------------------------------------------- |
|
40 | 42 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom |
41 | 43 | # ones. |
42 | 44 | extensions = [ |
| 45 | + "sphinx_rtd_theme", |
43 | 46 | "sphinx.ext.autodoc", |
44 | 47 | "sphinx.ext.napoleon", |
45 | 48 | "sphinx.ext.intersphinx", |
46 | | - "sphinx_rtd_theme", |
47 | 49 | "sphinx_gallery.gen_gallery", |
48 | 50 | ] |
49 | 51 |
|
|
64 | 66 | master_doc = "index" |
65 | 67 |
|
66 | 68 |
|
| 69 | +# -- Build wheel so Pyodide examples can use exactly this version of rendercanvas ----------------------------------------------------- |
| 70 | + |
| 71 | +short_version = ".".join(str(i) for i in rendercanvas.version_info[:3]) |
| 72 | +wheel_name = f"rendercanvas-{short_version}-py3-none-any.whl" |
| 73 | + |
| 74 | +# Build the wheel |
| 75 | +toml_filename = os.path.join(ROOT_DIR, "pyproject.toml") |
| 76 | +flit.main(["-f", toml_filename, "build", "--no-use-vcs", "--format", "wheel"]) |
| 77 | +wheel_filename = os.path.join(ROOT_DIR, "dist", wheel_name) |
| 78 | +assert os.path.isfile(wheel_filename), f"{wheel_name} does not exist" |
| 79 | + |
| 80 | +# Copy into static |
| 81 | +print("Copy wheel to static dir") |
| 82 | +shutil.copy( |
| 83 | + wheel_filename, |
| 84 | + os.path.join(ROOT_DIR, "docs", "static", wheel_name), |
| 85 | +) |
| 86 | + |
| 87 | + |
67 | 88 | # -- Sphinx Gallery ----------------------------------------------------- |
68 | 89 |
|
| 90 | +iframe_placeholder_rst = """ |
| 91 | +.. only:: html |
| 92 | +
|
| 93 | + Interactive example |
| 94 | + =================== |
| 95 | +
|
| 96 | + This uses Pyodide. If this does not work, your browser may not have sufficient support for wasm/pyodide/wgpu (check your browser dev console). |
| 97 | +
|
| 98 | + .. raw:: html |
| 99 | +
|
| 100 | + <iframe src="pyodide.html#example.py"></iframe> |
| 101 | +""" |
| 102 | + |
| 103 | +python_files = {} |
| 104 | + |
| 105 | + |
| 106 | +def add_pyodide_to_examples(app): |
| 107 | + if app.builder.name != "html": |
| 108 | + return |
| 109 | + |
| 110 | + gallery_dir = os.path.join(ROOT_DIR, "docs", "gallery") |
| 111 | + |
| 112 | + for fname in os.listdir(gallery_dir): |
| 113 | + filename = os.path.join(gallery_dir, fname) |
| 114 | + if not fname.endswith(".py"): |
| 115 | + continue |
| 116 | + with open(filename, "rb") as f: |
| 117 | + py = f.read().decode() |
| 118 | + if fname in ["drag.py", "noise.py", "snake.py"]: |
| 119 | + # todo: later we detect by using a special comment in the py file |
| 120 | + print("Adding Pyodide example to", fname) |
| 121 | + fname_rst = fname.replace(".py", ".rst") |
| 122 | + # Update rst file |
| 123 | + rst = iframe_placeholder_rst.replace("example.py", fname) |
| 124 | + with open(os.path.join(gallery_dir, fname_rst), "ab") as f: |
| 125 | + f.write(rst.encode()) |
| 126 | + python_files[fname] = py |
| 127 | + |
| 128 | + |
| 129 | +def add_files_to_run_pyodide_examples(app, exception): |
| 130 | + if app.builder.name != "html": |
| 131 | + return |
| 132 | + |
| 133 | + gallery_build_dir = os.path.join(app.outdir, "gallery") |
| 134 | + |
| 135 | + # Write html file that can load pyodide examples |
| 136 | + with open( |
| 137 | + os.path.join(ROOT_DIR, "docs", "static", "_pyodide_iframe.html"), "rb" |
| 138 | + ) as f: |
| 139 | + html = f.read().decode() |
| 140 | + html = html.replace('"rendercanvas"', f'"../_static/{wheel_name}"') |
| 141 | + with open(os.path.join(gallery_build_dir, "pyodide.html"), "wb") as f: |
| 142 | + f.write(html.encode()) |
| 143 | + |
| 144 | + # Write the python files |
| 145 | + for fname, py in python_files.items(): |
| 146 | + print("Writing", fname) |
| 147 | + with open(os.path.join(gallery_build_dir, fname), "wb") as f: |
| 148 | + f.write(py.encode()) |
| 149 | + |
| 150 | + |
69 | 151 | # Suppress "cannot cache unpickable configuration value" for sphinx_gallery_conf |
70 | 152 | # See https://github.com/sphinx-doc/sphinx/issues/12300 |
71 | 153 | suppress_warnings = ["config.cache"] |
|
75 | 157 | "gallery_dirs": "gallery", |
76 | 158 | "backreferences_dir": "gallery/backreferences", |
77 | 159 | "doc_module": ("rendercanvas",), |
78 | | - # "image_scrapers": (),, |
| 160 | + # "image_scrapers": (), |
79 | 161 | "remove_config_comments": True, |
80 | 162 | "examples_dirs": "../examples/", |
| 163 | + "ignore_pattern": r"serve_browser_examples\.py", |
81 | 164 | } |
82 | 165 |
|
83 | 166 | # -- Options for HTML output ------------------------------------------------- |
|
92 | 175 | # so a file named "default.css" will overwrite the builtin "default.css". |
93 | 176 | html_static_path = ["static"] |
94 | 177 | html_css_files = ["custom.css"] |
| 178 | + |
| 179 | + |
| 180 | +def setup(app): |
| 181 | + app.connect("builder-inited", add_pyodide_to_examples) |
| 182 | + app.connect("build-finished", add_files_to_run_pyodide_examples) |
0 commit comments