unitlab 2.3.33__py3-none-any.whl → 2.3.35__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.
unitlab/auto_tunnel.py DELETED
@@ -1,174 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Automatic Tunnel Creation - Simplest approach using cloudflared's built-in quick tunnel
4
- No API tokens needed!
5
- """
6
-
7
- import subprocess
8
- import time
9
- import re
10
- import os
11
-
12
- class AutoTunnel:
13
- def __init__(self, device_id=None):
14
- """
15
- Initialize auto tunnel - no credentials needed!
16
- """
17
- self.device_id = device_id or "device"
18
- self.jupyter_process = None
19
- self.tunnel_process = None
20
- self.tunnel_url = None
21
-
22
- def get_cloudflared_path(self):
23
- """Get or download cloudflared binary"""
24
- import platform
25
-
26
- # Check if exists in system
27
- import shutil
28
- if shutil.which("cloudflared"):
29
- return "cloudflared"
30
-
31
- # Check local
32
- local_bin = os.path.expanduser("~/.local/bin/cloudflared")
33
- if os.path.exists(local_bin):
34
- return local_bin
35
-
36
- # Download it
37
- print("📦 Downloading cloudflared...")
38
- system = platform.system().lower()
39
- if system == "linux":
40
- arch = "amd64" if "x86" in platform.machine() else "arm64"
41
- url = "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-{}".format(arch)
42
-
43
- os.makedirs(os.path.expanduser("~/.local/bin"), exist_ok=True)
44
- subprocess.run("curl -L {} -o {}".format(url, local_bin), shell=True, capture_output=True)
45
- subprocess.run("chmod +x {}".format(local_bin), shell=True)
46
- print("✅ cloudflared downloaded")
47
- return local_bin
48
-
49
- return "cloudflared"
50
-
51
- def start_jupyter(self):
52
- """Start Jupyter notebook"""
53
- print("🚀 Starting Jupyter on port 8888...")
54
-
55
- cmd = [
56
- "jupyter", "notebook",
57
- "--port", "8888",
58
- "--no-browser",
59
- "--ip", "0.0.0.0",
60
- "--NotebookApp.token=''",
61
- "--NotebookApp.password=''",
62
- "--NotebookApp.allow_origin='*'"
63
- ]
64
-
65
- self.jupyter_process = subprocess.Popen(
66
- cmd,
67
- stdout=subprocess.PIPE,
68
- stderr=subprocess.PIPE
69
- )
70
-
71
- time.sleep(3)
72
- print("✅ Jupyter started")
73
- return True
74
-
75
- def start_tunnel(self):
76
- """Start tunnel using cloudflared quick tunnel - no auth needed!"""
77
- print("🔧 Starting automatic tunnel (no credentials needed)...")
78
-
79
- cloudflared = self.get_cloudflared_path()
80
-
81
- # Use cloudflared's quick tunnel feature - generates random URL
82
- cmd = [
83
- cloudflared,
84
- "tunnel",
85
- "--url", "http://localhost:8888"
86
- ]
87
-
88
- self.tunnel_process = subprocess.Popen(
89
- cmd,
90
- stdout=subprocess.PIPE,
91
- stderr=subprocess.STDOUT,
92
- text=True,
93
- bufsize=1
94
- )
95
-
96
- # Read output to get the tunnel URL
97
- print("⏳ Waiting for tunnel URL...")
98
- for _ in range(30): # Wait up to 30 seconds
99
- line = self.tunnel_process.stdout.readline()
100
- if line:
101
- # Look for the tunnel URL in output
102
- match = re.search(r'https://[a-zA-Z0-9-]+\.trycloudflare\.com', line)
103
- if match:
104
- self.tunnel_url = match.group(0)
105
- print("✅ Tunnel created: {}".format(self.tunnel_url))
106
- return True
107
- time.sleep(1)
108
-
109
- print("❌ Failed to get tunnel URL")
110
- return False
111
-
112
- def start(self):
113
- """Start everything - super simple!"""
114
- try:
115
- print("="*50)
116
- print("🌐 Automatic Cloudflare Tunnel (No Auth Needed!)")
117
- print("Device: {}".format(self.device_id))
118
- print("="*50)
119
-
120
- # 1. Start Jupyter
121
- if not self.start_jupyter():
122
- raise Exception("Failed to start Jupyter")
123
-
124
- # 2. Start tunnel (automatic, no credentials)
125
- if not self.start_tunnel():
126
- raise Exception("Failed to start tunnel")
127
-
128
- print("\n" + "="*50)
129
- print("🎉 SUCCESS! Your Jupyter is accessible at:")
130
- print(" {}".format(self.tunnel_url))
131
- print("="*50)
132
- print("\n⚠️ Note: This URL is temporary and random")
133
- print("For persistent URLs, use Cloudflare API approach")
134
-
135
- return True
136
-
137
- except Exception as e:
138
- print("❌ Error: {}".format(e))
139
- self.stop()
140
- return False
141
-
142
- def stop(self):
143
- """Stop everything"""
144
- if self.jupyter_process:
145
- self.jupyter_process.terminate()
146
- if self.tunnel_process:
147
- self.tunnel_process.terminate()
148
-
149
- def run(self):
150
- """Run and keep alive"""
151
- try:
152
- if self.start():
153
- print("\nPress Ctrl+C to stop...")
154
- while True:
155
- time.sleep(1)
156
- except KeyboardInterrupt:
157
- print("\n⏹️ Shutting down...")
158
- self.stop()
159
- print("👋 Goodbye!")
160
-
161
-
162
- def main():
163
- """Test automatic tunnel"""
164
- import platform
165
- device_id = platform.node()
166
-
167
- print("Starting auto tunnel for: {}".format(device_id))
168
-
169
- tunnel = AutoTunnel(device_id=device_id)
170
- tunnel.run()
171
-
172
-
173
- if __name__ == "__main__":
174
- main()
unitlab/binary_manager.py DELETED
@@ -1,154 +0,0 @@
1
- import os
2
- import platform
3
- import hashlib
4
- import urllib.request
5
- from pathlib import Path
6
- import stat
7
- import json
8
-
9
- class CloudflaredBinaryManager:
10
- """
11
- Manages cloudflared binary automatically
12
- - Downloads on first use
13
- - Caches for future use
14
- - Verifies integrity
15
- - Zero user configuration
16
- """
17
-
18
- # Binary URLs and checksums
19
- BINARIES = {
20
- 'linux-amd64': {
21
- 'url': 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64',
22
- 'checksum': 'sha256:...', # Add real checksums
23
- 'filename': 'cloudflared'
24
- },
25
- 'linux-arm64': {
26
- 'url': 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64',
27
- 'checksum': 'sha256:...',
28
- 'filename': 'cloudflared'
29
- },
30
- 'darwin-amd64': {
31
- 'url': 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-darwin-amd64.tgz',
32
- 'checksum': 'sha256:...',
33
- 'filename': 'cloudflared',
34
- 'compressed': True
35
- },
36
- 'windows-amd64': {
37
- 'url': 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe',
38
- 'checksum': 'sha256:...',
39
- 'filename': 'cloudflared.exe'
40
- }
41
- }
42
-
43
- def __init__(self):
44
- # User's home directory - works on all platforms
45
- self.cache_dir = Path.home() / '.unitlab' / 'bin'
46
- self.cache_dir.mkdir(parents=True, exist_ok=True)
47
-
48
- # Detect platform once
49
- self.platform_key = self._detect_platform()
50
-
51
- def _detect_platform(self):
52
- """Detect OS and architecture"""
53
- system = platform.system().lower()
54
- machine = platform.machine().lower()
55
-
56
- if system == 'linux':
57
- if machine in ['x86_64', 'amd64']:
58
- return 'linux-amd64'
59
- elif machine in ['aarch64', 'arm64']:
60
- return 'linux-arm64'
61
-
62
- elif system == 'darwin': # macOS
63
- # Check if ARM (M1/M2) or Intel
64
- if machine == 'arm64':
65
- return 'darwin-arm64'
66
- return 'darwin-amd64'
67
-
68
- elif system == 'windows':
69
- return 'windows-amd64'
70
-
71
- raise RuntimeError(f"Unsupported platform: {system} {machine}")
72
-
73
- def get_binary_path(self):
74
- """Get path to cloudflared binary, downloading if needed"""
75
-
76
- binary_info = self.BINARIES[self.platform_key]
77
- binary_path = self.cache_dir / binary_info['filename']
78
-
79
- # Check if already downloaded
80
- if binary_path.exists():
81
- print("✓ Using cached cloudflared")
82
- return str(binary_path)
83
-
84
- # Download for first time
85
- print("🔄 First time setup - downloading cloudflared...")
86
- self._download_binary(binary_info, binary_path)
87
-
88
- return str(binary_path)
89
-
90
- def _download_binary(self, info, target_path):
91
- """Download and verify binary"""
92
-
93
- # Create SSL context to handle certificate issues
94
- import ssl
95
- ssl_context = ssl.create_default_context()
96
- ssl_context.check_hostname = False
97
- ssl_context.verify_mode = ssl.CERT_NONE
98
-
99
- # Download with progress bar
100
- def download_progress(block_num, block_size, total_size):
101
- downloaded = block_num * block_size
102
- if total_size > 0:
103
- percent = min(downloaded * 100 / total_size, 100)
104
- print(f"Downloading: {percent:.0f}%", end='\r')
105
- else:
106
- print(f"Downloading: {downloaded} bytes", end='\r')
107
-
108
- temp_file = target_path.with_suffix('.tmp')
109
-
110
- try:
111
- # Download file with SSL context
112
- req = urllib.request.Request(info['url'], headers={'User-Agent': 'Mozilla/5.0'})
113
- with urllib.request.urlopen(req, context=ssl_context) as response:
114
- total_size = int(response.headers.get('Content-Length', 0))
115
-
116
- with open(temp_file, 'wb') as f:
117
- downloaded = 0
118
- block_size = 8192
119
- while True:
120
- chunk = response.read(block_size)
121
- if not chunk:
122
- break
123
- f.write(chunk)
124
- downloaded += len(chunk)
125
- if total_size > 0:
126
- percent = min(downloaded * 100 / total_size, 100)
127
- print(f"Downloading: {percent:.0f}%", end='\r')
128
- print("\n✓ Download complete")
129
-
130
- # Handle compressed files (macOS .tgz)
131
- if info.get('compressed'):
132
- import tarfile
133
- with tarfile.open(temp_file, 'r:gz') as tar:
134
- # Extract just the cloudflared binary
135
- tar.extract('cloudflared', self.cache_dir)
136
- temp_file.unlink()
137
- else:
138
- # Move to final location
139
- temp_file.rename(target_path)
140
-
141
- # Make executable on Unix systems
142
- if platform.system() != 'Windows':
143
- target_path.chmod(target_path.stat().st_mode | stat.S_IEXEC)
144
-
145
- print("✓ Cloudflared ready!")
146
-
147
- except Exception as e:
148
- print(f"❌ Download failed: {e}")
149
- if temp_file.exists():
150
- temp_file.unlink()
151
- raise
152
-
153
-
154
-