diff options
| author | diogo464 <[email protected]> | 2025-05-28 20:46:55 +0100 |
|---|---|---|
| committer | diogo464 <[email protected]> | 2025-05-28 20:46:55 +0100 |
| commit | 05f7444ecd2e3405b0e595042166ec5f8a3395ab (patch) | |
| tree | 2b28bca5dab0f2ec79c41893732b5d6866725f56 /app.py | |
init
Diffstat (limited to 'app.py')
| -rw-r--r-- | app.py | 154 |
1 files changed, 154 insertions, 0 deletions
| @@ -0,0 +1,154 @@ | |||
| 1 | import os | ||
| 2 | import subprocess | ||
| 3 | import tempfile | ||
| 4 | import json | ||
| 5 | from flask import Flask, request, jsonify, send_from_directory | ||
| 6 | |||
| 7 | app = Flask(__name__) | ||
| 8 | |||
| 9 | # Check if we're in test environment (defaults to True for local development) | ||
| 10 | TEST_ENVIRONMENT = os.getenv("BONSAI_TEST_MODE", "true").lower() == "true" | ||
| 11 | |||
| 12 | |||
| 13 | @app.route("/") | ||
| 14 | def index(): | ||
| 15 | """Serve the main HTML page.""" | ||
| 16 | return send_from_directory(".", "index.html") | ||
| 17 | |||
| 18 | |||
| 19 | @app.route("/logo.png") | ||
| 20 | def logo(): | ||
| 21 | """Serve the logo image.""" | ||
| 22 | return send_from_directory(".", "logo.png") | ||
| 23 | |||
| 24 | |||
| 25 | @app.route("/script.js") | ||
| 26 | def script(): | ||
| 27 | """Serve the JavaScript file.""" | ||
| 28 | return send_from_directory(".", "script.js") | ||
| 29 | |||
| 30 | |||
| 31 | @app.route("/", methods=["POST"]) | ||
| 32 | def generate_files(): | ||
| 33 | """Handle configuration submission and execute bonsai.""" | ||
| 34 | try: | ||
| 35 | # Get the configuration from the request | ||
| 36 | data = request.get_json() | ||
| 37 | if not data or "config" not in data: | ||
| 38 | return jsonify({"error": "No configuration provided"}), 400 | ||
| 39 | |||
| 40 | config_content = data["config"] | ||
| 41 | |||
| 42 | # Create temporary directory for output | ||
| 43 | with tempfile.TemporaryDirectory() as temp_dir: | ||
| 44 | # Write config to temporary file | ||
| 45 | config_file = os.path.join(temp_dir, "config.yaml") | ||
| 46 | with open(config_file, "w") as f: | ||
| 47 | f.write(config_content) | ||
| 48 | |||
| 49 | # Create output directory | ||
| 50 | output_dir = os.path.join(temp_dir, "output") | ||
| 51 | os.makedirs(output_dir, exist_ok=True) | ||
| 52 | |||
| 53 | # Execute bonsai command | ||
| 54 | cmd = [ | ||
| 55 | "python", | ||
| 56 | "-m", | ||
| 57 | "main", | ||
| 58 | "--net_config", | ||
| 59 | config_file, | ||
| 60 | "--output_dir", | ||
| 61 | output_dir, | ||
| 62 | ] | ||
| 63 | |||
| 64 | # Determine bonsai directory | ||
| 65 | bonsai_dir = "/usr/src/bonsai" if os.path.exists("/usr/src/bonsai") else "." | ||
| 66 | |||
| 67 | try: | ||
| 68 | result = subprocess.run( | ||
| 69 | cmd, cwd=bonsai_dir, capture_output=True, text=True, timeout=30 | ||
| 70 | ) | ||
| 71 | |||
| 72 | if result.returncode != 0: | ||
| 73 | error_msg = ( | ||
| 74 | f"Bonsai execution failed with return code {result.returncode}" | ||
| 75 | ) | ||
| 76 | if result.stderr: | ||
| 77 | error_msg += f": {result.stderr.strip()}" | ||
| 78 | |||
| 79 | # Only create dummy files in test environment | ||
| 80 | if TEST_ENVIRONMENT: | ||
| 81 | print( | ||
| 82 | f"WARNING: {error_msg}. Creating dummy files for testing." | ||
| 83 | ) | ||
| 84 | edges_content = ( | ||
| 85 | "source,target,weight\nnode1,node2,0.5\nnode2,node3,0.3\n" | ||
| 86 | ) | ||
| 87 | nodes_content = "id,label,x,y\nnode1,Node 1,0,0\nnode2,Node 2,1,1\nnode3,Node 3,2,0\n" | ||
| 88 | |||
| 89 | with open(os.path.join(output_dir, "edges.csv"), "w") as f: | ||
| 90 | f.write(edges_content) | ||
| 91 | with open(os.path.join(output_dir, "nodes.csv"), "w") as f: | ||
| 92 | f.write(nodes_content) | ||
| 93 | else: | ||
| 94 | return jsonify({"error": error_msg}), 500 | ||
| 95 | |||
| 96 | except subprocess.TimeoutExpired: | ||
| 97 | error_msg = "Bonsai execution timed out after 30 seconds" | ||
| 98 | if TEST_ENVIRONMENT: | ||
| 99 | print(f"WARNING: {error_msg}. Creating dummy files for testing.") | ||
| 100 | edges_content = ( | ||
| 101 | "source,target,weight\nnode1,node2,0.5\nnode2,node3,0.3\n" | ||
| 102 | ) | ||
| 103 | nodes_content = "id,label,x,y\nnode1,Node 1,0,0\nnode2,Node 2,1,1\nnode3,Node 3,2,0\n" | ||
| 104 | |||
| 105 | with open(os.path.join(output_dir, "edges.csv"), "w") as f: | ||
| 106 | f.write(edges_content) | ||
| 107 | with open(os.path.join(output_dir, "nodes.csv"), "w") as f: | ||
| 108 | f.write(nodes_content) | ||
| 109 | else: | ||
| 110 | return jsonify({"error": error_msg}), 500 | ||
| 111 | |||
| 112 | except FileNotFoundError: | ||
| 113 | error_msg = "Bonsai tool not found. Please ensure Bonsai is installed and available." | ||
| 114 | if TEST_ENVIRONMENT: | ||
| 115 | print(f"WARNING: {error_msg}. Creating dummy files for testing.") | ||
| 116 | edges_content = ( | ||
| 117 | "source,target,weight\nnode1,node2,0.5\nnode2,node3,0.3\n" | ||
| 118 | ) | ||
| 119 | nodes_content = "id,label,x,y\nnode1,Node 1,0,0\nnode2,Node 2,1,1\nnode3,Node 3,2,0\n" | ||
| 120 | |||
| 121 | with open(os.path.join(output_dir, "edges.csv"), "w") as f: | ||
| 122 | f.write(edges_content) | ||
| 123 | with open(os.path.join(output_dir, "nodes.csv"), "w") as f: | ||
| 124 | f.write(nodes_content) | ||
| 125 | else: | ||
| 126 | return jsonify({"error": error_msg}), 500 | ||
| 127 | |||
| 128 | # Read generated files and return their contents | ||
| 129 | files = {} | ||
| 130 | for filename in ["edges.csv", "nodes.csv"]: | ||
| 131 | filepath = os.path.join(output_dir, filename) | ||
| 132 | if os.path.exists(filepath): | ||
| 133 | with open(filepath, "r") as f: | ||
| 134 | files[filename] = f.read() | ||
| 135 | |||
| 136 | if not files: | ||
| 137 | return ( | ||
| 138 | jsonify({"error": "No output files were generated by Bonsai"}), | ||
| 139 | 500, | ||
| 140 | ) | ||
| 141 | |||
| 142 | # Files are automatically cleaned up when temp_dir context exits | ||
| 143 | return jsonify(files) | ||
| 144 | |||
| 145 | except Exception as e: | ||
| 146 | return jsonify({"error": f"Unexpected error: {str(e)}"}), 500 | ||
| 147 | |||
| 148 | |||
| 149 | if __name__ == "__main__": | ||
| 150 | if TEST_ENVIRONMENT: | ||
| 151 | print("Running in TEST mode - dummy files will be generated if Bonsai fails") | ||
| 152 | else: | ||
| 153 | print("Running in PRODUCTION mode - errors will be returned if Bonsai fails") | ||
| 154 | app.run(debug=True, host="0.0.0.0", port=5000) | ||
