more-compute 0.2.6__py3-none-any.whl → 0.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- frontend/app/globals.css +38 -133
- frontend/app/layout.tsx +54 -5
- frontend/components/Notebook.tsx +9 -1
- frontend/components/cell/CellButton.tsx +2 -2
- frontend/components/cell/MonacoCell.tsx +1 -15
- frontend/components/output/CellOutput.tsx +77 -17
- frontend/components/output/ErrorDisplay.tsx +3 -28
- frontend/components/popups/FilterPopup.tsx +24 -24
- frontend/components/popups/MetricsPopup.tsx +42 -7
- frontend/components/popups/PackagesPopup.tsx +2 -1
- frontend/lib/api.ts +6 -2
- frontend/lib/settings.ts +7 -0
- frontend/lib/websocket-native.ts +3 -0
- frontend/styling_README.md +15 -2
- kernel_run.py +26 -13
- {more_compute-0.2.6.dist-info → more_compute-0.3.1.dist-info}/METADATA +1 -1
- {more_compute-0.2.6.dist-info → more_compute-0.3.1.dist-info}/RECORD +29 -27
- morecompute/__version__.py +1 -1
- morecompute/execution/executor.py +12 -5
- morecompute/execution/worker.py +93 -1
- morecompute/server.py +4 -0
- morecompute/utils/cell_magics.py +713 -0
- morecompute/utils/line_magics.py +949 -0
- morecompute/utils/shell_utils.py +68 -0
- morecompute/utils/special_commands.py +106 -173
- frontend/components/Cell.tsx +0 -383
- {more_compute-0.2.6.dist-info → more_compute-0.3.1.dist-info}/WHEEL +0 -0
- {more_compute-0.2.6.dist-info → more_compute-0.3.1.dist-info}/entry_points.txt +0 -0
- {more_compute-0.2.6.dist-info → more_compute-0.3.1.dist-info}/licenses/LICENSE +0 -0
- {more_compute-0.2.6.dist-info → more_compute-0.3.1.dist-info}/top_level.txt +0 -0
morecompute/execution/worker.py
CHANGED
|
@@ -10,6 +10,91 @@ import matplotlib
|
|
|
10
10
|
matplotlib.use('Agg')
|
|
11
11
|
import matplotlib.pyplot as plt
|
|
12
12
|
import re
|
|
13
|
+
import subprocess
|
|
14
|
+
import shlex
|
|
15
|
+
import platform
|
|
16
|
+
|
|
17
|
+
# Import shared shell command utilities
|
|
18
|
+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
19
|
+
from utils.shell_utils import prepare_shell_command, prepare_shell_environment
|
|
20
|
+
|
|
21
|
+
def _preprocess_shell_commands(code: str) -> str:
|
|
22
|
+
"""
|
|
23
|
+
Preprocess code to transform IPython-style shell commands (!cmd) into Python function calls.
|
|
24
|
+
Returns transformed code with shell commands converted to _run_shell_command() calls.
|
|
25
|
+
"""
|
|
26
|
+
lines = code.split('\n')
|
|
27
|
+
transformed_lines = []
|
|
28
|
+
|
|
29
|
+
for line in lines:
|
|
30
|
+
# Match shell commands: " !pip install pandas"
|
|
31
|
+
shell_match = re.match(r'^(\s*)!(.+)$', line)
|
|
32
|
+
|
|
33
|
+
if shell_match:
|
|
34
|
+
indent = shell_match.group(1)
|
|
35
|
+
shell_cmd = shell_match.group(2).strip()
|
|
36
|
+
# Use repr() for proper escaping
|
|
37
|
+
shell_cmd_repr = repr(shell_cmd)
|
|
38
|
+
# Transform to function call
|
|
39
|
+
transformed = f"{indent}_run_shell_command({shell_cmd_repr})"
|
|
40
|
+
transformed_lines.append(transformed)
|
|
41
|
+
else:
|
|
42
|
+
transformed_lines.append(line)
|
|
43
|
+
|
|
44
|
+
return '\n'.join(transformed_lines)
|
|
45
|
+
|
|
46
|
+
def _inject_shell_command_function(globals_dict: dict):
|
|
47
|
+
"""Inject the _run_shell_command function into globals if not present."""
|
|
48
|
+
if '_run_shell_command' not in globals_dict:
|
|
49
|
+
def _run_shell_command(cmd: str):
|
|
50
|
+
"""Execute a shell command synchronously with streaming output"""
|
|
51
|
+
# Prepare command and environment (using shared utilities)
|
|
52
|
+
shell_cmd = prepare_shell_command(cmd)
|
|
53
|
+
env = prepare_shell_environment(cmd)
|
|
54
|
+
|
|
55
|
+
# Use Popen for real-time streaming
|
|
56
|
+
process = subprocess.Popen(
|
|
57
|
+
shell_cmd,
|
|
58
|
+
stdout=subprocess.PIPE,
|
|
59
|
+
stderr=subprocess.PIPE,
|
|
60
|
+
text=True,
|
|
61
|
+
bufsize=1, # Line buffered
|
|
62
|
+
env=env
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Stream output line by line
|
|
66
|
+
import threading
|
|
67
|
+
|
|
68
|
+
def read_stream(stream, output_type):
|
|
69
|
+
try:
|
|
70
|
+
for line in iter(stream.readline, ''):
|
|
71
|
+
if not line:
|
|
72
|
+
break
|
|
73
|
+
if output_type == 'stdout':
|
|
74
|
+
print(line, end='')
|
|
75
|
+
sys.stdout.flush()
|
|
76
|
+
else:
|
|
77
|
+
print(line, end='', file=sys.stderr)
|
|
78
|
+
sys.stderr.flush()
|
|
79
|
+
except Exception:
|
|
80
|
+
pass
|
|
81
|
+
finally:
|
|
82
|
+
stream.close()
|
|
83
|
+
|
|
84
|
+
stdout_thread = threading.Thread(target=read_stream, args=(process.stdout, 'stdout'))
|
|
85
|
+
stderr_thread = threading.Thread(target=read_stream, args=(process.stderr, 'stderr'))
|
|
86
|
+
stdout_thread.daemon = True
|
|
87
|
+
stderr_thread.daemon = True
|
|
88
|
+
stdout_thread.start()
|
|
89
|
+
stderr_thread.start()
|
|
90
|
+
|
|
91
|
+
return_code = process.wait()
|
|
92
|
+
stdout_thread.join()
|
|
93
|
+
stderr_thread.join()
|
|
94
|
+
|
|
95
|
+
return return_code
|
|
96
|
+
|
|
97
|
+
globals_dict['_run_shell_command'] = _run_shell_command
|
|
13
98
|
|
|
14
99
|
def _setup_signals():
|
|
15
100
|
def _handler(signum, frame):
|
|
@@ -232,7 +317,14 @@ def worker_main():
|
|
|
232
317
|
error_payload = None
|
|
233
318
|
start = time.time()
|
|
234
319
|
try:
|
|
235
|
-
|
|
320
|
+
# Preprocess shell commands (!cmd) to Python function calls
|
|
321
|
+
# This allows code like "import os; !pip install pandas" to work
|
|
322
|
+
preprocessed_code = _preprocess_shell_commands(code)
|
|
323
|
+
|
|
324
|
+
# Inject shell command function into globals if needed
|
|
325
|
+
_inject_shell_command_function(g)
|
|
326
|
+
|
|
327
|
+
compiled = compile(preprocessed_code, '<cell>', 'exec')
|
|
236
328
|
exec(compiled, g, l)
|
|
237
329
|
|
|
238
330
|
# Try to evaluate last expression for display (like Jupyter)
|
morecompute/server.py
CHANGED
|
@@ -119,6 +119,10 @@ async def list_installed_packages(force_refresh: bool = False):
|
|
|
119
119
|
global pod_manager
|
|
120
120
|
cache_key = "packages_list"
|
|
121
121
|
|
|
122
|
+
# Clear cache if force refresh is requested
|
|
123
|
+
if force_refresh and cache_key in packages_cache:
|
|
124
|
+
del packages_cache[cache_key]
|
|
125
|
+
|
|
122
126
|
# Check cache first unless force refresh is requested
|
|
123
127
|
if not force_refresh and cache_key in packages_cache:
|
|
124
128
|
return packages_cache[cache_key]
|