Skip to content

Commit 0778dbc

Browse files
Merge branch 'code-editor' into integrate-code-editor-with-events
2 parents e40280a + fd6bc15 commit 0778dbc

File tree

5 files changed

+34
-75
lines changed

5 files changed

+34
-75
lines changed

package-lock.json

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"react-dom": "^18.2.0",
1919
"react-plotly.js": "^2.6.0",
2020
"@uiw/react-codemirror": "^4.24.2",
21-
"@uiw/codemirror-theme-vscode": "^4.24.2"
21+
"@uiw/codemirror-theme-vscode": "^4.24.2",
22+
"@codemirror/lang-python": "^6.2.1"
2223
},
2324
"devDependencies": {
2425
"@eslint/js": "^9.25.0",

src/PythonCodeEditor.jsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useState, useCallback } from 'react';
22
import CodeMirror from '@uiw/react-codemirror';
33
import { vscodeDark } from '@uiw/codemirror-theme-vscode';
4+
import { python } from '@codemirror/lang-python';
45
import { getApiEndpoint } from './config.js';
56

67

@@ -57,12 +58,12 @@ const PythonCodeEditor = ({
5758
disabled={isExecuting}
5859
className="execute-btn"
5960
>
60-
{isExecuting ? 'Executing...' : 'Execute Code'}
61+
{isExecuting ? 'Executing...' : 'Test Code'}
6162
</button>
6263
</div>
6364

6465
<div className="editor-container" style={{ height }}>
65-
<CodeMirror value={code} onChange={handleCodeChange} theme={vscodeDark} options={{ fontSize: 24 }}/>
66+
<CodeMirror value={code} onChange={handleCodeChange} extensions={[python({ python: true })]} theme={vscodeDark} options={{ fontSize: 24 }}/>
6667
</div>
6768

6869
{executionResult && (

src/backend.py

Lines changed: 6 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
from .pathsim_utils import make_pathsim_model, map_str_to_object
1616
from pathsim.blocks import Scope, Spectrum
1717

18-
# Import pathsim_utils to share eval_namespace
19-
from . import pathsim_utils
20-
2118
# Sphinx imports for docstring processing
2219
from docutils.core import publish_parts
2320

@@ -324,14 +321,9 @@ def run_pathsim():
324321
return jsonify({"success": False, "error": f"Server error: {str(e)}"}), 500
325322

326323

327-
# Global namespace for user-defined variables and functions
328-
eval_namespace = {}
329-
330-
331324
@app.route("/execute-python", methods=["POST"])
332325
def execute_python():
333-
"""Execute Python code and update the global eval_namespace with any new variables/functions."""
334-
global eval_namespace
326+
"""Execute Python code and returns variables/functions."""
335327

336328
try:
337329
data = request.json
@@ -341,16 +333,13 @@ def execute_python():
341333
return jsonify({"success": False, "error": "No code provided"}), 400
342334

343335
# Create a temporary namespace that includes current eval_namespace
344-
temp_namespace = eval_namespace.copy()
345-
temp_namespace.update(globals())
336+
temp_namespace = {}
337+
# temp_namespace.update(globals())
346338

347339
# Capture stdout and stderr
348340
stdout_capture = io.StringIO()
349341
stderr_capture = io.StringIO()
350342

351-
# Track variables before execution
352-
vars_before = set(temp_namespace.keys())
353-
354343
try:
355344
with redirect_stdout(stdout_capture), redirect_stderr(stderr_capture):
356345
exec(code, temp_namespace)
@@ -363,37 +352,29 @@ def execute_python():
363352
return jsonify({"success": False, "error": error_output}), 400
364353

365354
# Find new variables and functions
366-
vars_after = set(temp_namespace.keys())
367-
new_vars = vars_after - vars_before
355+
vars = set(temp_namespace.keys())
356+
# new_vars = vars_after - vars_before
368357

369358
# Filter out built-ins and modules, keep user-defined items
370359
user_variables = {}
371360
user_functions = []
372361

373-
for var_name in new_vars:
362+
for var_name in vars:
374363
if not var_name.startswith("__"):
375364
value = temp_namespace[var_name]
376365
if callable(value) and hasattr(value, "__name__"):
377366
user_functions.append(var_name)
378-
# Add function to eval_namespace
379-
eval_namespace[var_name] = value
380367
else:
381368
# Try to serialize the value for display
382369
try:
383370
if isinstance(value, (int, float, str, bool, list, dict)):
384371
user_variables[var_name] = value
385372
else:
386373
user_variables[var_name] = str(value)
387-
# Add variable to eval_namespace
388-
eval_namespace[var_name] = value
389374
except Exception:
390375
user_variables[var_name] = (
391376
f"<{type(value).__name__} object>"
392377
)
393-
eval_namespace[var_name] = value
394-
395-
# Sync with pathsim_utils shared_eval_namespace
396-
pathsim_utils.shared_eval_namespace.update(eval_namespace)
397378

398379
return jsonify(
399380
{
@@ -414,48 +395,6 @@ def execute_python():
414395
return jsonify({"success": False, "error": f"Server error: {str(e)}"}), 500
415396

416397

417-
@app.route("/get-eval-namespace", methods=["GET"])
418-
def get_eval_namespace():
419-
"""Get the current eval_namespace for debugging/inspection."""
420-
try:
421-
# Create a serializable version of the namespace
422-
serializable_namespace = {}
423-
424-
for key, value in eval_namespace.items():
425-
if callable(value):
426-
serializable_namespace[key] = f"<function {key}>"
427-
else:
428-
try:
429-
if isinstance(value, (int, float, str, bool, list, dict)):
430-
serializable_namespace[key] = value
431-
else:
432-
serializable_namespace[key] = str(value)
433-
except Exception:
434-
serializable_namespace[key] = f"<{type(value).__name__} object>"
435-
436-
return jsonify({"success": True, "namespace": serializable_namespace})
437-
except Exception as e:
438-
return jsonify(
439-
{"success": False, "error": f"Error retrieving namespace: {str(e)}"}
440-
), 500
441-
442-
443-
@app.route("/clear-eval-namespace", methods=["POST"])
444-
def clear_eval_namespace():
445-
"""Clear the eval_namespace."""
446-
global eval_namespace
447-
try:
448-
eval_namespace.clear()
449-
pathsim_utils.shared_eval_namespace.clear()
450-
return jsonify(
451-
{"success": True, "message": "Eval namespace cleared successfully."}
452-
)
453-
except Exception as e:
454-
return jsonify(
455-
{"success": False, "error": f"Error clearing namespace: {str(e)}"}
456-
), 500
457-
458-
459398
# Catch-all route for React Router (SPA routing)
460399
@app.route("/<path:path>")
461400
def catch_all(path):

src/pathsim_utils.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636
from flask import jsonify
3737
import inspect
3838

39-
# Shared eval_namespace - will be set by backend
40-
shared_eval_namespace = {}
4139

4240
NAME_TO_SOLVER = {
4341
"SSPRK22": pathsim.solvers.SSPRK22,
@@ -112,9 +110,6 @@ def make_global_variables(global_vars):
112110
# Return a namespace dictionary containing the global variables
113111
global_namespace = globals().copy()
114112

115-
# Include shared variables from the code editor
116-
global_namespace.update(shared_eval_namespace)
117-
118113
for var in global_vars:
119114
var_name = var.get("name", "").strip()
120115
var_value = var.get("value", "")

0 commit comments

Comments
 (0)