more-compute 0.1.0__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.
- kernel_run.py +283 -0
- more_compute-0.1.0.dist-info/METADATA +163 -0
- more_compute-0.1.0.dist-info/RECORD +26 -0
- more_compute-0.1.0.dist-info/WHEEL +5 -0
- more_compute-0.1.0.dist-info/entry_points.txt +2 -0
- more_compute-0.1.0.dist-info/licenses/LICENSE +21 -0
- more_compute-0.1.0.dist-info/top_level.txt +2 -0
- morecompute/__init__.py +6 -0
- morecompute/cli.py +31 -0
- morecompute/execution/__init__.py +5 -0
- morecompute/execution/__main__.py +10 -0
- morecompute/execution/executor.py +381 -0
- morecompute/execution/worker.py +244 -0
- morecompute/notebook.py +81 -0
- morecompute/process_worker.py +209 -0
- morecompute/server.py +641 -0
- morecompute/services/pod_manager.py +503 -0
- morecompute/services/prime_intellect.py +316 -0
- morecompute/static/styles.css +1056 -0
- morecompute/utils/__init__.py +17 -0
- morecompute/utils/cache_util.py +23 -0
- morecompute/utils/error_utils.py +322 -0
- morecompute/utils/notebook_util.py +44 -0
- morecompute/utils/python_environment_util.py +197 -0
- morecompute/utils/special_commands.py +458 -0
- morecompute/utils/system_environment_util.py +134 -0
kernel_run.py
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
import os
|
|
7
|
+
import time
|
|
8
|
+
import signal
|
|
9
|
+
import threading
|
|
10
|
+
import webbrowser
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from morecompute.notebook import Notebook
|
|
14
|
+
|
|
15
|
+
DEFAULT_NOTEBOOK_NAME = "notebook.ipynb"
|
|
16
|
+
|
|
17
|
+
class NotebookLauncher:
|
|
18
|
+
def __init__(self, notebook_path: Path, debug=False):
|
|
19
|
+
self.backend_process = None
|
|
20
|
+
self.frontend_process = None
|
|
21
|
+
self.root_dir = Path(__file__).parent
|
|
22
|
+
self.debug = debug
|
|
23
|
+
self.notebook_path = notebook_path
|
|
24
|
+
root_dir = notebook_path.parent if notebook_path.parent != Path('') else Path.cwd()
|
|
25
|
+
os.environ["MORECOMPUTE_ROOT"] = str(root_dir.resolve())
|
|
26
|
+
os.environ["MORECOMPUTE_NOTEBOOK_PATH"] = str(self.notebook_path)
|
|
27
|
+
|
|
28
|
+
def start_backend(self):
|
|
29
|
+
"""Start the FastAPI backend server"""
|
|
30
|
+
try:
|
|
31
|
+
# Force a stable port (default 8000); if busy, ask to free it
|
|
32
|
+
chosen_port = int(os.getenv("MORECOMPUTE_PORT", "8000"))
|
|
33
|
+
self._ensure_port_available(chosen_port)
|
|
34
|
+
cmd = [
|
|
35
|
+
sys.executable,
|
|
36
|
+
"-m",
|
|
37
|
+
"uvicorn",
|
|
38
|
+
"morecompute.server:app",
|
|
39
|
+
"--host",
|
|
40
|
+
"localhost",
|
|
41
|
+
"--port",
|
|
42
|
+
str(chosen_port),
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
# Enable autoreload only when debugging or explicitly requested
|
|
46
|
+
enable_reload = (
|
|
47
|
+
self.debug
|
|
48
|
+
or os.getenv("MORECOMPUTE_RELOAD", "0") == "1"
|
|
49
|
+
)
|
|
50
|
+
if enable_reload:
|
|
51
|
+
# Limit reload scope to backend code and exclude large/changing artifacts
|
|
52
|
+
cmd.extend([
|
|
53
|
+
"--reload",
|
|
54
|
+
"--reload-dir", "morecompute",
|
|
55
|
+
"--reload-exclude", "*.ipynb",
|
|
56
|
+
"--reload-exclude", "frontend",
|
|
57
|
+
"--reload-exclude", "assets",
|
|
58
|
+
])
|
|
59
|
+
|
|
60
|
+
if not self.debug:
|
|
61
|
+
cmd.extend(["--log-level", "error", "--no-access-log"])
|
|
62
|
+
|
|
63
|
+
stdout_dest = None if self.debug else subprocess.DEVNULL
|
|
64
|
+
stderr_dest = None if self.debug else subprocess.DEVNULL
|
|
65
|
+
|
|
66
|
+
# Start the FastAPI server using uvicorn
|
|
67
|
+
self.backend_process = subprocess.Popen(
|
|
68
|
+
cmd,
|
|
69
|
+
cwd=self.root_dir,
|
|
70
|
+
stdout=stdout_dest,
|
|
71
|
+
stderr=stderr_dest,
|
|
72
|
+
)
|
|
73
|
+
# Save for later printing/opening
|
|
74
|
+
self.backend_port = chosen_port
|
|
75
|
+
except Exception as e:
|
|
76
|
+
print(f"Failed to start backend: {e}")
|
|
77
|
+
sys.exit(1)
|
|
78
|
+
|
|
79
|
+
def _ensure_port_available(self, port: int) -> None:
|
|
80
|
+
import socket
|
|
81
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
82
|
+
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
83
|
+
try:
|
|
84
|
+
s.bind(("127.0.0.1", port))
|
|
85
|
+
return # free
|
|
86
|
+
except OSError:
|
|
87
|
+
pass # in use
|
|
88
|
+
# Port is in use - show processes and ask to kill
|
|
89
|
+
print(f"\nPort {port} appears to be in use.")
|
|
90
|
+
pids = []
|
|
91
|
+
try:
|
|
92
|
+
out = subprocess.check_output(["lsof", "-nP", f"-iTCP:{port}", "-sTCP:LISTEN"]).decode("utf-8", errors="ignore")
|
|
93
|
+
print(out)
|
|
94
|
+
for line in out.splitlines()[1:]:
|
|
95
|
+
parts = line.split()
|
|
96
|
+
if len(parts) > 1 and parts[1].isdigit():
|
|
97
|
+
pids.append(int(parts[1]))
|
|
98
|
+
except Exception:
|
|
99
|
+
print("Could not list processes with lsof. You may need to free the port manually.")
|
|
100
|
+
resp = input(f"Kill processes on port {port} and continue? [y/N]: ").strip().lower()
|
|
101
|
+
if resp != "y":
|
|
102
|
+
print("Aborting. Set MORECOMPUTE_PORT to a different port to override.")
|
|
103
|
+
sys.exit(1)
|
|
104
|
+
# Attempt to kill
|
|
105
|
+
for pid in pids:
|
|
106
|
+
try:
|
|
107
|
+
os.kill(pid, 9)
|
|
108
|
+
except Exception:
|
|
109
|
+
pass
|
|
110
|
+
# Fallback: kill known patterns
|
|
111
|
+
try:
|
|
112
|
+
subprocess.run(["pkill", "-f", "uvicorn .*morecompute.server:app"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
113
|
+
except Exception:
|
|
114
|
+
pass
|
|
115
|
+
try:
|
|
116
|
+
subprocess.run(["pkill", "-f", "morecompute.execution.worker"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
117
|
+
except Exception:
|
|
118
|
+
pass
|
|
119
|
+
# Brief pause to let the OS release the port
|
|
120
|
+
time.sleep(0.5)
|
|
121
|
+
# Poll until it binds
|
|
122
|
+
start = time.time()
|
|
123
|
+
while time.time() - start < 5.0:
|
|
124
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s2:
|
|
125
|
+
s2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
126
|
+
try:
|
|
127
|
+
s2.bind(("127.0.0.1", port))
|
|
128
|
+
return
|
|
129
|
+
except OSError:
|
|
130
|
+
time.sleep(0.25)
|
|
131
|
+
print(f"Port {port} still busy. Please free it or set MORECOMPUTE_PORT to another port.")
|
|
132
|
+
sys.exit(1)
|
|
133
|
+
|
|
134
|
+
def start_frontend(self):
|
|
135
|
+
"""Start the Next.js frontend server"""
|
|
136
|
+
try:
|
|
137
|
+
frontend_dir = self.root_dir / "frontend"
|
|
138
|
+
|
|
139
|
+
# Check if node_modules exists
|
|
140
|
+
if not (frontend_dir / "node_modules").exists():
|
|
141
|
+
print("Installing dependencies...")
|
|
142
|
+
subprocess.run(
|
|
143
|
+
["npm", "install"],
|
|
144
|
+
cwd=frontend_dir,
|
|
145
|
+
check=True,
|
|
146
|
+
stdout=subprocess.DEVNULL,
|
|
147
|
+
stderr=subprocess.DEVNULL
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
fe_stdout = None if self.debug else subprocess.DEVNULL
|
|
151
|
+
fe_stderr = None if self.debug else subprocess.DEVNULL
|
|
152
|
+
|
|
153
|
+
self.frontend_process = subprocess.Popen(
|
|
154
|
+
["npm", "run", "dev"],
|
|
155
|
+
cwd=frontend_dir,
|
|
156
|
+
stdout=fe_stdout,
|
|
157
|
+
stderr=fe_stderr
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# Wait a bit then open browser
|
|
161
|
+
time.sleep(3)
|
|
162
|
+
webbrowser.open("http://localhost:3000")
|
|
163
|
+
|
|
164
|
+
except Exception as e:
|
|
165
|
+
print(f"Failed to start frontend: {e}")
|
|
166
|
+
self.cleanup()
|
|
167
|
+
sys.exit(1)
|
|
168
|
+
|
|
169
|
+
def cleanup(self):
|
|
170
|
+
"""Clean up processes on exit"""
|
|
171
|
+
if self.frontend_process:
|
|
172
|
+
self.frontend_process.terminate()
|
|
173
|
+
try:
|
|
174
|
+
self.frontend_process.wait(timeout=5)
|
|
175
|
+
except subprocess.TimeoutExpired:
|
|
176
|
+
self.frontend_process.kill()
|
|
177
|
+
|
|
178
|
+
if self.backend_process:
|
|
179
|
+
self.backend_process.terminate()
|
|
180
|
+
try:
|
|
181
|
+
self.backend_process.wait(timeout=5)
|
|
182
|
+
except subprocess.TimeoutExpired:
|
|
183
|
+
self.backend_process.kill()
|
|
184
|
+
|
|
185
|
+
def run(self):
|
|
186
|
+
"""Main run method"""
|
|
187
|
+
print("\n Edit notebook in your browser!\n")
|
|
188
|
+
print(" ➜ URL: http://localhost:3000\n")
|
|
189
|
+
|
|
190
|
+
# Set up signal handlers
|
|
191
|
+
def signal_handler(signum, frame):
|
|
192
|
+
print("\n\n Thanks for using MoreCompute!\n")
|
|
193
|
+
self.cleanup()
|
|
194
|
+
sys.exit(0)
|
|
195
|
+
|
|
196
|
+
signal.signal(signal.SIGINT, signal_handler)
|
|
197
|
+
signal.signal(signal.SIGTERM, signal_handler)
|
|
198
|
+
|
|
199
|
+
# Start services
|
|
200
|
+
self.start_backend()
|
|
201
|
+
time.sleep(1)
|
|
202
|
+
self.start_frontend()
|
|
203
|
+
|
|
204
|
+
# Wait for processes
|
|
205
|
+
try:
|
|
206
|
+
while True:
|
|
207
|
+
# Check if processes are still running
|
|
208
|
+
if self.backend_process and self.backend_process.poll() is not None:
|
|
209
|
+
self.cleanup()
|
|
210
|
+
sys.exit(1)
|
|
211
|
+
|
|
212
|
+
if self.frontend_process and self.frontend_process.poll() is not None:
|
|
213
|
+
self.cleanup()
|
|
214
|
+
sys.exit(1)
|
|
215
|
+
|
|
216
|
+
time.sleep(1)
|
|
217
|
+
|
|
218
|
+
except KeyboardInterrupt:
|
|
219
|
+
print("\n\n Thanks for using MoreCompute!\n")
|
|
220
|
+
self.cleanup()
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
224
|
+
parser = argparse.ArgumentParser(description="Launch the MoreCompute notebook")
|
|
225
|
+
parser.add_argument(
|
|
226
|
+
"notebook_path",
|
|
227
|
+
nargs="?",
|
|
228
|
+
default=None,
|
|
229
|
+
help="Path to the .ipynb notebook file",
|
|
230
|
+
)
|
|
231
|
+
parser.add_argument(
|
|
232
|
+
"-debug",
|
|
233
|
+
"--debug",
|
|
234
|
+
action="store_true",
|
|
235
|
+
help="Show backend/frontend logs (hidden by default)",
|
|
236
|
+
)
|
|
237
|
+
return parser
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def ensure_notebook_exists(notebook_path: Path):
|
|
241
|
+
if notebook_path.exists():
|
|
242
|
+
if notebook_path.suffix != '.ipynb':
|
|
243
|
+
raise ValueError("Notebook path must be a .ipynb file")
|
|
244
|
+
return
|
|
245
|
+
|
|
246
|
+
if notebook_path.suffix != '.ipynb':
|
|
247
|
+
raise ValueError("Notebook path must end with .ipynb")
|
|
248
|
+
|
|
249
|
+
notebook_path.parent.mkdir(parents=True, exist_ok=True)
|
|
250
|
+
notebook = Notebook()
|
|
251
|
+
notebook.save_to_file(str(notebook_path))
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def main(argv=None):
|
|
255
|
+
parser = build_parser()
|
|
256
|
+
args = parser.parse_args(argv)
|
|
257
|
+
raw_notebook_path = args.notebook_path
|
|
258
|
+
|
|
259
|
+
if raw_notebook_path == "new":
|
|
260
|
+
from datetime import datetime
|
|
261
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
262
|
+
raw_notebook_path = f"notebook_{timestamp}.ipynb"
|
|
263
|
+
print(f"Creating new notebook: {raw_notebook_path}")
|
|
264
|
+
|
|
265
|
+
notebook_path_env = os.getenv("MORECOMPUTE_NOTEBOOK_PATH")
|
|
266
|
+
if raw_notebook_path is None:
|
|
267
|
+
raw_notebook_path = notebook_path_env
|
|
268
|
+
|
|
269
|
+
if raw_notebook_path is None:
|
|
270
|
+
raw_notebook_path = DEFAULT_NOTEBOOK_NAME
|
|
271
|
+
|
|
272
|
+
notebook_path = Path(raw_notebook_path).expanduser().resolve()
|
|
273
|
+
ensure_notebook_exists(notebook_path)
|
|
274
|
+
|
|
275
|
+
launcher = NotebookLauncher(
|
|
276
|
+
notebook_path=notebook_path,
|
|
277
|
+
debug=args.debug
|
|
278
|
+
)
|
|
279
|
+
launcher.run()
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
if __name__ == "__main__":
|
|
283
|
+
main()
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: more-compute
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: An interactive notebook environment for local and GPU computing
|
|
5
|
+
Home-page: https://github.com/DannyMang/MORECOMPUTE
|
|
6
|
+
Author: MoreCompute Team
|
|
7
|
+
Author-email: MoreCompute Team <hello@morecompute.dev>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/DannyMang/MORECOMPUTE
|
|
10
|
+
Project-URL: Repository, https://github.com/DannyMang/MORECOMPUTE
|
|
11
|
+
Project-URL: Issues, https://github.com/DannyMang/MORECOMPUTE/issues
|
|
12
|
+
Keywords: jupyter,notebook,gpu,computing,interactive
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Requires-Python: >=3.8
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: fastapi>=0.104.0
|
|
27
|
+
Requires-Dist: uvicorn[standard]>=0.24.0
|
|
28
|
+
Requires-Dist: python-multipart>=0.0.5
|
|
29
|
+
Requires-Dist: nbformat>=5.0.0
|
|
30
|
+
Requires-Dist: click>=8.0.0
|
|
31
|
+
Requires-Dist: pyzmq>=25.0.0
|
|
32
|
+
Requires-Dist: psutil>=5.9.0
|
|
33
|
+
Requires-Dist: httpx>=0.24.0
|
|
34
|
+
Requires-Dist: cachetools>=5.3.0
|
|
35
|
+
Requires-Dist: matplotlib>=3.5.0
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: home-page
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
Dynamic: requires-python
|
|
40
|
+
|
|
41
|
+
# more-compute
|
|
42
|
+
An interactive notebook environment similar to Marimo and Google Colab that runs locally.
|
|
43
|
+
|
|
44
|
+
For references:
|
|
45
|
+
|
|
46
|
+
https://marimo.io/
|
|
47
|
+
|
|
48
|
+
https://colab.google/
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
FOR LOCAL DEVELOPMENT:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install -e .
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
(NOT IMPLEMENTED YET, TO-DO SET UP ON PyPi)
|
|
61
|
+
pip install more-compute
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Usage
|
|
65
|
+
|
|
66
|
+
### Create a new notebook
|
|
67
|
+
```bash
|
|
68
|
+
more-compute new
|
|
69
|
+
```
|
|
70
|
+
This creates a timestamped notebook like `notebook_20241007_153302.ipynb`
|
|
71
|
+
|
|
72
|
+
Or run directly:
|
|
73
|
+
```bash
|
|
74
|
+
python3 kernel_run.py new
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Open an existing notebook
|
|
78
|
+
```bash
|
|
79
|
+
# Open a specific notebook
|
|
80
|
+
more-compute your_notebook.ipynb
|
|
81
|
+
|
|
82
|
+
# Or run directly
|
|
83
|
+
python3 kernel_run.py your_notebook.ipynb
|
|
84
|
+
|
|
85
|
+
# If no path provided, opens default notebook
|
|
86
|
+
more-compute
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Features
|
|
90
|
+
|
|
91
|
+
- **Interactive notebook interface** similar to Google Colab
|
|
92
|
+
- **Support for both `.py` and `.ipynb` files**
|
|
93
|
+
- **Real-time cell execution** with execution timing
|
|
94
|
+
- **Magic commands** support:
|
|
95
|
+
- `!pip install package_name` - Install Python packages
|
|
96
|
+
- `!ls` - List directory contents
|
|
97
|
+
- `!pwd` - Print working directory
|
|
98
|
+
- `!any_shell_command` - Run any shell command
|
|
99
|
+
- **Visual execution feedback**:
|
|
100
|
+
- ✅ Green check icon for successful execution
|
|
101
|
+
- ❌ Red X icon for failed execution
|
|
102
|
+
- Execution timing displayed for each cell
|
|
103
|
+
- **Local development environment** - runs on your machine
|
|
104
|
+
- **Web-based interface** accessible via localhost
|
|
105
|
+
- **Cell management**:
|
|
106
|
+
- Add/delete cells
|
|
107
|
+
- Drag and drop to reorder
|
|
108
|
+
- Code and Markdown cell types
|
|
109
|
+
|
|
110
|
+
## Usage Examples
|
|
111
|
+
|
|
112
|
+
### Installing and Using Libraries
|
|
113
|
+
```python
|
|
114
|
+
# Install packages using magic commands (like Colab)
|
|
115
|
+
!pip install pandas numpy matplotlib
|
|
116
|
+
|
|
117
|
+
# Import and use them
|
|
118
|
+
import pandas as pd
|
|
119
|
+
import numpy as np
|
|
120
|
+
import matplotlib.pyplot as plt
|
|
121
|
+
|
|
122
|
+
# Create some data
|
|
123
|
+
df = pd.DataFrame({
|
|
124
|
+
'x': np.range(10),
|
|
125
|
+
'y': np.random.randn(10)
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
print(df.head())
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Shell Commands
|
|
132
|
+
```bash
|
|
133
|
+
# List files
|
|
134
|
+
!ls -la
|
|
135
|
+
|
|
136
|
+
# Check current directory
|
|
137
|
+
!pwd
|
|
138
|
+
|
|
139
|
+
# Run any shell command
|
|
140
|
+
!echo "Hello from the shell!"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Data Analysis Example
|
|
144
|
+
```python
|
|
145
|
+
# Load data
|
|
146
|
+
data = pd.read_csv('your_data.csv')
|
|
147
|
+
|
|
148
|
+
# Analyze
|
|
149
|
+
data.describe()
|
|
150
|
+
|
|
151
|
+
# Plot
|
|
152
|
+
plt.figure(figsize=(10, 6))
|
|
153
|
+
plt.plot(data['x'], data['y'])
|
|
154
|
+
plt.title('My Analysis')
|
|
155
|
+
plt.show()
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Development
|
|
159
|
+
|
|
160
|
+
To install in development mode:
|
|
161
|
+
```bash
|
|
162
|
+
pip install -e .
|
|
163
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
kernel_run.py,sha256=tZwu-cmeqnBfzD7vme2o_-ZMFCWCZzAPBWwPfod2_ZY,9640
|
|
2
|
+
more_compute-0.1.0.dist-info/licenses/LICENSE,sha256=0Ot-XIetYt06iay6IhtpJkruD-cLZtjyv7_aIEE-oSc,1073
|
|
3
|
+
morecompute/__init__.py,sha256=pcMVq8Q7qb42AOn7tqgoZJOi3epDDBnEriiv2WVKnXY,87
|
|
4
|
+
morecompute/cli.py,sha256=kVvzvPBqF8xO6UuhU_-TBn99nKwJ405R2mAS6zU0KBc,734
|
|
5
|
+
morecompute/notebook.py,sha256=vSKSjaIZzUbDoPEk2yb4rmM9LA71o44WGqmFen0b70c,3114
|
|
6
|
+
morecompute/process_worker.py,sha256=KsE3r-XpkYGuyO4w3t54VKkD51LfNHAZc3TYattMtrg,7185
|
|
7
|
+
morecompute/server.py,sha256=sAZ9X4CJpd59ZDYjdu7LDYy_Nwd1gQYF9Dn5uRP_uDU,24071
|
|
8
|
+
morecompute/execution/__init__.py,sha256=jPmBmq8BZWbUEY9XFSpqt5FkgX04uNS10WnUlr7Rnms,134
|
|
9
|
+
morecompute/execution/__main__.py,sha256=pAWB_1bn99u8Gb-tVMSMI-NYvbYbDiwbn40L0a0djeA,202
|
|
10
|
+
morecompute/execution/executor.py,sha256=Ngpd_PwQkgvX_ZMEcwGXPKY0OTKtwiI-lrv1ITPF9cA,19399
|
|
11
|
+
morecompute/execution/worker.py,sha256=1XAFMUDbc2A1lO7xUKS9s69Vu6gOMOPdkr8w1pOoQU4,9634
|
|
12
|
+
morecompute/services/pod_manager.py,sha256=eGZyLBiAXVk-rSdQJZOkw5scEHdofwqxNGUJIu78yI0,16684
|
|
13
|
+
morecompute/services/prime_intellect.py,sha256=xHzfKgg8pIKikcMCzgz_5RvXC_LekeIR2gq2hDYRRm4,9129
|
|
14
|
+
morecompute/static/styles.css,sha256=el_NtrUMbAUNSiMVBn1xlG70m3iPv7dyaIbWQMexhsY,19277
|
|
15
|
+
morecompute/utils/__init__.py,sha256=VIxCL3S1pnjEs4cjKGZqZB68_P8FegdeMIqBjJhI5jQ,419
|
|
16
|
+
morecompute/utils/cache_util.py,sha256=lVlXudHvtyvSo_kCSxORJrI85Jod8FrQLbI2f_JOIbA,661
|
|
17
|
+
morecompute/utils/error_utils.py,sha256=e50WLFdD6ngIC30xAgrzdTYtD8tPOIFkKAAh_sPbK0I,11667
|
|
18
|
+
morecompute/utils/notebook_util.py,sha256=3hH94dtXvhizRVTU9a2b38m_51Y4igoXpkjAXUqpVBQ,1353
|
|
19
|
+
morecompute/utils/python_environment_util.py,sha256=l8WWWPwKbypknw8GwL22NXCji5i1FOy1vWG47J6og4g,7441
|
|
20
|
+
morecompute/utils/special_commands.py,sha256=oCmAjKUsIOPIfobaJFDWhN2D5PLkKZtQozR3XAdIMe8,18653
|
|
21
|
+
morecompute/utils/system_environment_util.py,sha256=32mQRubo0i4X61o-825T7m-eUSidcEp07qkInP1sWZA,4774
|
|
22
|
+
more_compute-0.1.0.dist-info/METADATA,sha256=TTuzochhvAsXky6P2Jpq5nmULreWY9edtu0x5lBC0Wk,3817
|
|
23
|
+
more_compute-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
24
|
+
more_compute-0.1.0.dist-info/entry_points.txt,sha256=xp7z9eRPNRM4oxkZZVlyXkhkSjN1AjoYI_B7qpDJ1bI,49
|
|
25
|
+
more_compute-0.1.0.dist-info/top_level.txt,sha256=bK5t6sP_R9xshwmWbm19ctLWV3tln2qRyDQH1xb6OfU,23
|
|
26
|
+
more_compute-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 MoreCompute Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
morecompute/__init__.py
ADDED
morecompute/cli.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from .notebook import Notebook
|
|
4
|
+
|
|
5
|
+
@click.group()
|
|
6
|
+
def main():
|
|
7
|
+
"""MoreCompute CLI."""
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@main.command()
|
|
11
|
+
@click.argument('notebook_path', required=True)
|
|
12
|
+
def new(notebook_path: str):
|
|
13
|
+
"""Create a new .ipynb notebook."""
|
|
14
|
+
path = Path(notebook_path).expanduser().resolve()
|
|
15
|
+
|
|
16
|
+
if path.suffix != '.ipynb':
|
|
17
|
+
raise click.UsageError("Only .ipynb notebooks are supported right now.")
|
|
18
|
+
|
|
19
|
+
if path.exists():
|
|
20
|
+
raise click.ClickException(f"File '{path}' already exists")
|
|
21
|
+
|
|
22
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
23
|
+
|
|
24
|
+
notebook = Notebook(str(path))
|
|
25
|
+
notebook.save_to_file(str(path))
|
|
26
|
+
|
|
27
|
+
click.echo(f"✅ Created notebook at {path}")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
if __name__ == '__main__':
|
|
31
|
+
main()
|