more-compute 0.1.0__tar.gz

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.
Files changed (33) hide show
  1. more_compute-0.1.0/LICENSE +21 -0
  2. more_compute-0.1.0/MANIFEST.in +2 -0
  3. more_compute-0.1.0/PKG-INFO +163 -0
  4. more_compute-0.1.0/README.md +123 -0
  5. more_compute-0.1.0/kernel_run.py +283 -0
  6. more_compute-0.1.0/more_compute.egg-info/PKG-INFO +163 -0
  7. more_compute-0.1.0/more_compute.egg-info/SOURCES.txt +31 -0
  8. more_compute-0.1.0/more_compute.egg-info/dependency_links.txt +1 -0
  9. more_compute-0.1.0/more_compute.egg-info/entry_points.txt +2 -0
  10. more_compute-0.1.0/more_compute.egg-info/requires.txt +10 -0
  11. more_compute-0.1.0/more_compute.egg-info/top_level.txt +2 -0
  12. more_compute-0.1.0/morecompute/__init__.py +6 -0
  13. more_compute-0.1.0/morecompute/cli.py +31 -0
  14. more_compute-0.1.0/morecompute/execution/__init__.py +5 -0
  15. more_compute-0.1.0/morecompute/execution/__main__.py +10 -0
  16. more_compute-0.1.0/morecompute/execution/executor.py +381 -0
  17. more_compute-0.1.0/morecompute/execution/worker.py +244 -0
  18. more_compute-0.1.0/morecompute/notebook.py +81 -0
  19. more_compute-0.1.0/morecompute/process_worker.py +209 -0
  20. more_compute-0.1.0/morecompute/server.py +641 -0
  21. more_compute-0.1.0/morecompute/services/pod_manager.py +503 -0
  22. more_compute-0.1.0/morecompute/services/prime_intellect.py +316 -0
  23. more_compute-0.1.0/morecompute/static/styles.css +1056 -0
  24. more_compute-0.1.0/morecompute/utils/__init__.py +17 -0
  25. more_compute-0.1.0/morecompute/utils/cache_util.py +23 -0
  26. more_compute-0.1.0/morecompute/utils/error_utils.py +322 -0
  27. more_compute-0.1.0/morecompute/utils/notebook_util.py +44 -0
  28. more_compute-0.1.0/morecompute/utils/python_environment_util.py +197 -0
  29. more_compute-0.1.0/morecompute/utils/special_commands.py +458 -0
  30. more_compute-0.1.0/morecompute/utils/system_environment_util.py +134 -0
  31. more_compute-0.1.0/pyproject.toml +54 -0
  32. more_compute-0.1.0/setup.cfg +4 -0
  33. more_compute-0.1.0/setup.py +48 -0
@@ -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.
@@ -0,0 +1,2 @@
1
+ include README.md
2
+ recursive-include morecompute/static *
@@ -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,123 @@
1
+ # more-compute
2
+ An interactive notebook environment similar to Marimo and Google Colab that runs locally.
3
+
4
+ For references:
5
+
6
+ https://marimo.io/
7
+
8
+ https://colab.google/
9
+
10
+
11
+ FOR LOCAL DEVELOPMENT:
12
+
13
+ ```bash
14
+ pip install -e .
15
+ ```
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ (NOT IMPLEMENTED YET, TO-DO SET UP ON PyPi)
21
+ pip install more-compute
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### Create a new notebook
27
+ ```bash
28
+ more-compute new
29
+ ```
30
+ This creates a timestamped notebook like `notebook_20241007_153302.ipynb`
31
+
32
+ Or run directly:
33
+ ```bash
34
+ python3 kernel_run.py new
35
+ ```
36
+
37
+ ### Open an existing notebook
38
+ ```bash
39
+ # Open a specific notebook
40
+ more-compute your_notebook.ipynb
41
+
42
+ # Or run directly
43
+ python3 kernel_run.py your_notebook.ipynb
44
+
45
+ # If no path provided, opens default notebook
46
+ more-compute
47
+ ```
48
+
49
+ ## Features
50
+
51
+ - **Interactive notebook interface** similar to Google Colab
52
+ - **Support for both `.py` and `.ipynb` files**
53
+ - **Real-time cell execution** with execution timing
54
+ - **Magic commands** support:
55
+ - `!pip install package_name` - Install Python packages
56
+ - `!ls` - List directory contents
57
+ - `!pwd` - Print working directory
58
+ - `!any_shell_command` - Run any shell command
59
+ - **Visual execution feedback**:
60
+ - ✅ Green check icon for successful execution
61
+ - ❌ Red X icon for failed execution
62
+ - Execution timing displayed for each cell
63
+ - **Local development environment** - runs on your machine
64
+ - **Web-based interface** accessible via localhost
65
+ - **Cell management**:
66
+ - Add/delete cells
67
+ - Drag and drop to reorder
68
+ - Code and Markdown cell types
69
+
70
+ ## Usage Examples
71
+
72
+ ### Installing and Using Libraries
73
+ ```python
74
+ # Install packages using magic commands (like Colab)
75
+ !pip install pandas numpy matplotlib
76
+
77
+ # Import and use them
78
+ import pandas as pd
79
+ import numpy as np
80
+ import matplotlib.pyplot as plt
81
+
82
+ # Create some data
83
+ df = pd.DataFrame({
84
+ 'x': np.range(10),
85
+ 'y': np.random.randn(10)
86
+ })
87
+
88
+ print(df.head())
89
+ ```
90
+
91
+ ### Shell Commands
92
+ ```bash
93
+ # List files
94
+ !ls -la
95
+
96
+ # Check current directory
97
+ !pwd
98
+
99
+ # Run any shell command
100
+ !echo "Hello from the shell!"
101
+ ```
102
+
103
+ ### Data Analysis Example
104
+ ```python
105
+ # Load data
106
+ data = pd.read_csv('your_data.csv')
107
+
108
+ # Analyze
109
+ data.describe()
110
+
111
+ # Plot
112
+ plt.figure(figsize=(10, 6))
113
+ plt.plot(data['x'], data['y'])
114
+ plt.title('My Analysis')
115
+ plt.show()
116
+ ```
117
+
118
+ ## Development
119
+
120
+ To install in development mode:
121
+ ```bash
122
+ pip install -e .
123
+ ```
@@ -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()