flashstudio 0.2.2__tar.gz → 0.2.3__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.
- {flashstudio-0.2.2/flashstudio.egg-info → flashstudio-0.2.3}/PKG-INFO +1 -1
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/__init__.py +1 -1
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/launcher.py +101 -43
- {flashstudio-0.2.2 → flashstudio-0.2.3/flashstudio.egg-info}/PKG-INFO +1 -1
- {flashstudio-0.2.2 → flashstudio-0.2.3}/pyproject.toml +1 -1
- {flashstudio-0.2.2 → flashstudio-0.2.3}/tests/test_launcher.py +47 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/LICENSE +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/README.md +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/README_PYPI.md +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/app.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/cli.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/components/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/components/dependencies.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/components/project_manager.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/components/sidebar.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/components/styles.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/components/wizard.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/components/zone_drawer/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/components/zone_drawer/index.html +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/constants.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/core/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/core/constants.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/_common.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/overview/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/overview/metrics.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/overview/pipeline_status.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/overview/project_banner.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/overview/quick_actions.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/overview/recent_runs.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/overview/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/page.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/_common.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/download/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/download/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/edit/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/edit/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/fix/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/fix/annotations.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/fix/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/helpers.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/page.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/preview/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/preview/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/quality/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/quality/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/upload/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/upload/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/verify/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/data/verify/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/export/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/export/_common.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/export/optimization/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/export/optimization/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/export/page.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/export/weights/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/export/weights/exporter.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/export/weights/settings.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/_common.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/data/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/data/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/model/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/model/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/page.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/run/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/run/detection.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/run/live.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/run/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/run/video.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/solution/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/inference/solution/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/_common.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/advanced/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/advanced/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/architecture/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/architecture/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/augment/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/augment/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/hyperparams/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/hyperparams/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/page.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/utils/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/model/utils/config.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/_common.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/compare/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/compare/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/launch/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/launch/controls.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/launch/dialogs.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/launch/preflight.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/launch/runner.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/launch/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/checkpoints.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/curves.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/dashboard.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/gt_verification.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/log_viewer.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/parsers.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/run_meta.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/tab.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/visualizations.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/page.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/utils/__init__.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/utils/config.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/utils/device.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/utils/filesystem.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/utils/jobs.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/utils/model_loader.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/utils/trainer_launcher.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/utils/training_hooks.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/utils/weight_hub.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio.egg-info/SOURCES.txt +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio.egg-info/dependency_links.txt +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio.egg-info/entry_points.txt +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio.egg-info/requires.txt +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio.egg-info/top_level.txt +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/setup.cfg +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/tests/test_app.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/tests/test_cli.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/tests/test_constants.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/tests/test_pipeline_flow.py +0 -0
- {flashstudio-0.2.2 → flashstudio-0.2.3}/tests/test_save_dir_compat.py +0 -0
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"""Launch FlashStudio UI — works locally and inside Google Colab."""
|
|
2
2
|
|
|
3
|
+
import atexit
|
|
4
|
+
import platform
|
|
3
5
|
import subprocess
|
|
4
6
|
import sys
|
|
5
7
|
import os
|
|
6
8
|
import re
|
|
9
|
+
import tempfile
|
|
7
10
|
import time as _time
|
|
8
11
|
from pathlib import Path
|
|
9
12
|
|
|
@@ -69,59 +72,115 @@ def launch(port: int = 8501, share: bool = True, ngrok_token: str | None = None)
|
|
|
69
72
|
# Tunnel helpers
|
|
70
73
|
# ---------------------------------------------------------------------------
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
# Keep tunnel processes referenced for the lifetime of the session. If these
|
|
76
|
+
# are garbage collected or terminated, the trycloudflare.com hostname starts
|
|
77
|
+
# returning Cloudflare error 1033 ("tunnel cannot resolve").
|
|
78
|
+
_LIVE_TUNNELS: list = []
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _shutdown_tunnels():
|
|
82
|
+
for proc in list(_LIVE_TUNNELS):
|
|
83
|
+
try:
|
|
84
|
+
if proc.poll() is None:
|
|
85
|
+
proc.terminate()
|
|
86
|
+
except OSError:
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
atexit.register(_shutdown_tunnels)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _cloudflared_binary() -> str | None:
|
|
94
|
+
"""Return a usable cloudflared binary path, downloading it if needed."""
|
|
95
|
+
import shutil
|
|
96
|
+
|
|
97
|
+
existing = shutil.which("cloudflared")
|
|
98
|
+
if existing:
|
|
99
|
+
return existing
|
|
74
100
|
|
|
75
|
-
Returns the public https URL or None on failure.
|
|
76
|
-
"""
|
|
77
101
|
binary = "/usr/local/bin/cloudflared"
|
|
78
|
-
if
|
|
102
|
+
if os.path.isfile(binary):
|
|
103
|
+
return binary
|
|
104
|
+
|
|
105
|
+
machine = platform.machine().lower()
|
|
106
|
+
arch = "arm64" if machine in ("aarch64", "arm64") else "amd64"
|
|
107
|
+
url = ("https://github.com/cloudflare/cloudflared/releases/latest/download/"
|
|
108
|
+
f"cloudflared-linux-{arch}")
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
subprocess.check_call(
|
|
112
|
+
["wget", "-q", url, "-O", binary],
|
|
113
|
+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
|
114
|
+
)
|
|
115
|
+
except Exception:
|
|
79
116
|
try:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
"https://github.com/cloudflare/cloudflared/releases/latest"
|
|
83
|
-
"/download/cloudflared-linux-amd64",
|
|
84
|
-
"-O", binary],
|
|
85
|
-
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
|
86
|
-
)
|
|
87
|
-
os.chmod(binary, 0o755)
|
|
117
|
+
import urllib.request
|
|
118
|
+
urllib.request.urlretrieve(url, binary)
|
|
88
119
|
except Exception:
|
|
89
120
|
return None
|
|
90
121
|
|
|
91
122
|
try:
|
|
92
|
-
|
|
93
|
-
[binary, "tunnel", "--url", f"http://localhost:{port}"],
|
|
94
|
-
stdout=subprocess.PIPE,
|
|
95
|
-
stderr=subprocess.PIPE,
|
|
96
|
-
)
|
|
123
|
+
os.chmod(binary, 0o755)
|
|
97
124
|
except OSError:
|
|
98
125
|
return None
|
|
126
|
+
return binary
|
|
99
127
|
|
|
100
|
-
|
|
101
|
-
|
|
128
|
+
|
|
129
|
+
def _start_cloudflared_tunnel(port: int) -> str | None:
|
|
130
|
+
"""Start a free Cloudflare quick tunnel (no sign-up required).
|
|
131
|
+
|
|
132
|
+
The tunnel process is kept alive for the rest of the session so the URL
|
|
133
|
+
stays usable. Returns the public https URL or None on failure.
|
|
134
|
+
"""
|
|
135
|
+
binary = _cloudflared_binary()
|
|
136
|
+
if not binary:
|
|
137
|
+
return None
|
|
138
|
+
|
|
139
|
+
fd, log_name = tempfile.mkstemp(prefix="flashstudio-cloudflared-",
|
|
140
|
+
suffix=".log")
|
|
141
|
+
os.close(fd)
|
|
142
|
+
log_path = Path(log_name)
|
|
102
143
|
try:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return None
|
|
114
|
-
continue
|
|
115
|
-
match = url_re.search(line)
|
|
116
|
-
if match:
|
|
117
|
-
return match.group(0)
|
|
118
|
-
finally:
|
|
119
|
-
if tunnel_proc.poll() is None:
|
|
120
|
-
try:
|
|
121
|
-
tunnel_proc.terminate()
|
|
122
|
-
except OSError:
|
|
123
|
-
pass
|
|
144
|
+
with open(log_path, "wb") as log_file:
|
|
145
|
+
proc = subprocess.Popen(
|
|
146
|
+
[binary, "tunnel", "--no-autoupdate", "--protocol", "http2",
|
|
147
|
+
"--url", f"http://127.0.0.1:{port}"],
|
|
148
|
+
stdout=log_file,
|
|
149
|
+
stderr=subprocess.STDOUT,
|
|
150
|
+
)
|
|
151
|
+
except OSError:
|
|
152
|
+
log_path.unlink(missing_ok=True)
|
|
153
|
+
return None
|
|
124
154
|
|
|
155
|
+
_LIVE_TUNNELS.append(proc)
|
|
156
|
+
|
|
157
|
+
url_re = re.compile(r"https://[a-z0-9-]+\.trycloudflare\.com")
|
|
158
|
+
deadline = _time.monotonic() + 30
|
|
159
|
+
while _time.monotonic() < deadline:
|
|
160
|
+
if proc.poll() is not None:
|
|
161
|
+
break
|
|
162
|
+
try:
|
|
163
|
+
output = log_path.read_text(encoding="utf-8", errors="replace")
|
|
164
|
+
except OSError:
|
|
165
|
+
output = ""
|
|
166
|
+
match = url_re.search(output)
|
|
167
|
+
if match:
|
|
168
|
+
return match.group(0)
|
|
169
|
+
_time.sleep(0.5)
|
|
170
|
+
|
|
171
|
+
# Timed out or cloudflared exited — clean up so we don't leak a dead tunnel.
|
|
172
|
+
if proc.poll() is None:
|
|
173
|
+
try:
|
|
174
|
+
proc.terminate()
|
|
175
|
+
proc.wait(timeout=5)
|
|
176
|
+
except Exception:
|
|
177
|
+
proc.kill()
|
|
178
|
+
if proc in _LIVE_TUNNELS:
|
|
179
|
+
_LIVE_TUNNELS.remove(proc)
|
|
180
|
+
try:
|
|
181
|
+
log_path.unlink(missing_ok=True)
|
|
182
|
+
except OSError:
|
|
183
|
+
pass
|
|
125
184
|
return None
|
|
126
185
|
|
|
127
186
|
|
|
@@ -226,9 +285,8 @@ def _launch_colab(app_path: str, port: int, share: bool, ngrok_token: str | None
|
|
|
226
285
|
print(" Skipped (using Colab proxy)")
|
|
227
286
|
|
|
228
287
|
# 3) Colab's built-in proxy (fallback — desktop browser only)
|
|
229
|
-
colab_proxy_url = _get_colab_proxy_url(port)
|
|
230
288
|
if not public_url:
|
|
231
|
-
public_url =
|
|
289
|
+
public_url = _get_colab_proxy_url(port)
|
|
232
290
|
|
|
233
291
|
# --- Display results ---
|
|
234
292
|
print(f"\n{'=' * 60}")
|
|
@@ -58,3 +58,50 @@ class TestLaunchFunction:
|
|
|
58
58
|
def test_import(self):
|
|
59
59
|
from flashstudio.launcher import launch
|
|
60
60
|
assert callable(launch)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class TestCloudflaredTunnel:
|
|
64
|
+
def test_tunnel_process_is_kept_alive(self):
|
|
65
|
+
"""The tunnel must stay running, otherwise trycloudflare returns 1033."""
|
|
66
|
+
from flashstudio import launcher
|
|
67
|
+
|
|
68
|
+
class FakeProc:
|
|
69
|
+
def __init__(self):
|
|
70
|
+
self.returncode = None
|
|
71
|
+
|
|
72
|
+
def poll(self):
|
|
73
|
+
return self.returncode
|
|
74
|
+
|
|
75
|
+
def terminate(self):
|
|
76
|
+
self.returncode = -15
|
|
77
|
+
|
|
78
|
+
def wait(self, timeout=None):
|
|
79
|
+
return self.returncode
|
|
80
|
+
|
|
81
|
+
def kill(self):
|
|
82
|
+
self.returncode = -9
|
|
83
|
+
|
|
84
|
+
fake_proc = FakeProc()
|
|
85
|
+
|
|
86
|
+
def fake_popen(cmd, stdout=None, stderr=None):
|
|
87
|
+
stdout.write(b"Your quick Tunnel: https://unit-test-tunnel.trycloudflare.com\n")
|
|
88
|
+
stdout.flush()
|
|
89
|
+
return fake_proc
|
|
90
|
+
|
|
91
|
+
launcher._LIVE_TUNNELS.clear()
|
|
92
|
+
try:
|
|
93
|
+
with patch.object(launcher, "_cloudflared_binary", return_value="/usr/bin/cloudflared"), \
|
|
94
|
+
patch.object(launcher.subprocess, "Popen", side_effect=fake_popen):
|
|
95
|
+
url = launcher._start_cloudflared_tunnel(8501)
|
|
96
|
+
|
|
97
|
+
assert url == "https://unit-test-tunnel.trycloudflare.com"
|
|
98
|
+
assert fake_proc.poll() is None
|
|
99
|
+
assert fake_proc in launcher._LIVE_TUNNELS
|
|
100
|
+
finally:
|
|
101
|
+
launcher._LIVE_TUNNELS.clear()
|
|
102
|
+
|
|
103
|
+
def test_missing_binary_returns_none(self):
|
|
104
|
+
from flashstudio import launcher
|
|
105
|
+
|
|
106
|
+
with patch.object(launcher, "_cloudflared_binary", return_value=None):
|
|
107
|
+
assert launcher._start_cloudflared_tunnel(8501) is None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/overview/pipeline_status.py
RENAMED
|
File without changes
|
{flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/overview/project_banner.py
RENAMED
|
File without changes
|
{flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/dashboard/overview/quick_actions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/gt_verification.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flashstudio-0.2.2 → flashstudio-0.2.3}/flashstudio/pages/training/monitor/visualizations.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|