(args)
| 144 | |
| 145 | |
| 146 | def run_static_export(args): |
| 147 | output_dir = args.static_output |
| 148 | os.makedirs(output_dir, exist_ok=True) |
| 149 | |
| 150 | # Load data and prepare JSON string |
| 151 | checkpoint_dir = find_latest_checkpoint(args.path) |
| 152 | if not checkpoint_dir: |
| 153 | raise RuntimeError(f"No checkpoint found in {args.path}") |
| 154 | data = load_evolution_data(checkpoint_dir) |
| 155 | logger.info(f"Exporting visualization for checkpoint: {checkpoint_dir}") |
| 156 | |
| 157 | with app.app_context(): |
| 158 | data_json = jsonify(data).get_data(as_text=True) |
| 159 | inlined = f"<script>window.STATIC_DATA = {data_json};</script>" |
| 160 | |
| 161 | # Load index.html template |
| 162 | templates_dir = os.path.join(os.path.dirname(__file__), "templates") |
| 163 | template_path = os.path.join(templates_dir, "index.html") |
| 164 | with open(template_path, "r", encoding="utf-8") as f: |
| 165 | html = f.read() |
| 166 | |
| 167 | # Insert static json data into the HTML |
| 168 | html = _re.sub(r"\{\{\s*url_for\('static', filename='([^']+)'\)\s*\}\}", r"static/\1", html) |
| 169 | script_tag_idx = html.find('<script type="module"') |
| 170 | |
| 171 | if script_tag_idx != -1: |
| 172 | html = html[:script_tag_idx] + inlined + "\n" + html[script_tag_idx:] |
| 173 | else: |
| 174 | html = html.replace("</body>", inlined + "\n</body>") |
| 175 | |
| 176 | with open(os.path.join(output_dir, "index.html"), "w", encoding="utf-8") as f: |
| 177 | f.write(html) |
| 178 | |
| 179 | # Copy over static files |
| 180 | static_src = os.path.join(os.path.dirname(__file__), "static") |
| 181 | static_dst = os.path.join(output_dir, "static") |
| 182 | if os.path.exists(static_dst): |
| 183 | shutil.rmtree(static_dst) |
| 184 | shutil.copytree(static_src, static_dst) |
| 185 | |
| 186 | logger.info( |
| 187 | f"Static export written to {output_dir}/\n" |
| 188 | f"Note: use a web server, not file://. " |
| 189 | f"Try: python3 -m http.server --directory {output_dir} 8080" |
| 190 | ) |
| 191 | |
| 192 | |
| 193 | # Manual mode blueprint mounted at /manual |
no test coverage detected