Source code for brian2wasm.__main__

import argparse
import shutil
import sys
import os
import platform
import subprocess

[docs] def main(): """ Command-line interface entry point for Brian2Wasm. This function validates the given script, injects the required ``set_device('wasm_standalone', …)`` call, ensures EMSDK is available (unless skipped), and executes the modified script. Parameters ---------- script : str Path to the Python model file. The file must exist, end with ``.py``, and must not call ``set_device`` directly, since this function injects the correct call automatically. --no-server : bool, optional If given, generates the WASM/HTML output without starting the local preview web server. Internally sets the environment variable ``BRIAN2WASM_NO_SERVER=1``. --skip-install : bool, optional If given, skips EMSDK installation and activation checks. Use this flag when you are certain EMSDK is already installed and properly configured in your environment. Raises ------ FileNotFoundError If the provided script path does not exist. ValueError If the provided file is not a Python ``.py`` script. RuntimeError If execution of the modified script fails for any reason. SystemExit If errors occur during validation or script execution, the process exits with status code ``1``. Returns ------- None This function is intended as a CLI entry point and does not return a value. """ parser = argparse.ArgumentParser( description="Brian2WASM CLI" ) parser.add_argument( "script", help="Path to the Python script to run" ) parser.add_argument( "--no-server", action="store_true", help="Generate files without starting the web server" ) parser.add_argument("--skip-install", action="store_true", help="Run Brian2WASM without installing/activating EMSDK" ) args = parser.parse_args() script_path = args.script # Check if the script exists and is a Python file if not os.path.isfile(script_path): full_path = os.path.abspath(script_path) print(f"Error: File '{full_path}' does not exist.", file=sys.stderr) sys.exit(1) if not script_path.endswith(".py"): print(f"Error: File '{script_path}' is not a Python script (.py).", file=sys.stderr) sys.exit(1) if not args.skip_install: # Check emsdk setup check_emsdk() # Read the original script with open(script_path, 'r') as f: script_content = f.read() # Get the script's directory and name script_dir = os.path.dirname(script_path) or '.' script_name = os.path.splitext(os.path.basename(script_path))[0] # Check if an HTML file with the same name exists html_file = f"{script_name}.html" html_file_path = os.path.join(script_dir, html_file) has_html_file = os.path.isfile(html_file_path) # Inject required lines at the top if has_html_file: print(f"HTML file found: '{html_file_path}'") injection = ( "from brian2 import set_device\n" "import brian2wasm\n" f"set_device('wasm_standalone', directory='{script_name}', html_file='{html_file}')\n" ) else: print("HTML file not found: using default HTML template.") injection = ( "from brian2 import set_device\n" "import brian2wasm\n" f"set_device('wasm_standalone', directory='{script_name}')\n" ) modified_script = injection + script_content # Set working directory to script's directory original_cwd = os.getcwd() os.chdir(script_dir) try: if args.no_server: os.environ['BRIAN2WASM_NO_SERVER'] = '1' print(f"Script path: {os.path.abspath(script_path)}") print(f"Directory: {script_dir}") exec_globals = {'__name__': '__main__', '__file__': os.path.abspath(script_path)} compiled_script = compile(modified_script, script_path, 'exec') exec(compiled_script, exec_globals) except Exception as e: print(f"Error running script: {e}", file=sys.stderr) sys.exit(1) finally: os.chdir(original_cwd)
[docs] def check_emsdk(): """ Verify that the Emscripten SDK (EMSDK) is installed and attempt to activate it. This function checks for EMSDK in the current environment, using either the system path (``emsdk`` executable) or the ``CONDA_EMSDK_DIR`` variable. If EMSDK is missing, it prints installation instructions and exits. If EMSDK is found but not activated, it attempts to activate the latest version, optionally prompting the user to install and activate it. Parameters ---------- None This function takes no arguments. Raises ------ SystemExit If EMSDK is not found, not activated, or installation/activation fails, the process exits with status code ``1``. RuntimeError If subprocess execution encounters an unexpected failure during EMSDK activation. Returns ------- None This function is intended as a setup check and does not return a value. Its success or failure is indicated by process exit. """ emsdk = shutil.which("emsdk") conda_emsdk_dir = os.environ.get("CONDA_EMSDK_DIR") if not emsdk and not conda_emsdk_dir: print("EMSDK and CONDA_EMSDK_DIR not found. That means EMSDK is not installed.") print(" ➤ If you are using **Pixi**, run:") print(" pixi add emsdk && pixi install") print(" ➤ If you are using **Conda**, run:") print(" conda install emsdk -c conda-forge") print(" ➤ Else refer to Emscripten documentation:") print(" https://emscripten.org/index.html#") sys.exit(1) print(f"EMSDK is installed and CONDA_EMSDK_DIR is found") try: print("Attempting to activate EMSDK with: emsdk activate latest") result = subprocess.run(["./emsdk", "activate", "latest"], cwd=conda_emsdk_dir, check=False, capture_output=True, text=True) if result.returncode != 0: print("Failed to activate EMSDK:") choice = input("Do you want to install and activate EMSDK now? (y/n) ") if choice == 'y': try: subprocess.run(["./emsdk", "install", "latest"], cwd=conda_emsdk_dir, check=True) print("EMSDK install & activation succeeded. You can run the script now.") except subprocess.CalledProcessError as e: print("Failed to activate EMSDK:") print(" ➤ Please run the following manually in your terminal and try again:") print(" cd $CONDA_EMSDK_DIR && ./emsdk install latest && ./emsdk activate latest") else: print(" ➤ Please run the following manually in your terminal and try again:") print(" cd $CONDA_EMSDK_DIR && ./emsdk install latest && ./emsdk activate latest") sys.exit(1) else: print("EMSDK activation succeeded.") except Exception as e: print(f"Error while running EMSDK activation: {e}") sys.exit(1)
if __name__ == "__main__": main()