litlaunch 1.0.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.
- litlaunch/__init__.py +192 -0
- litlaunch/__main__.py +8 -0
- litlaunch/_protocols.py +35 -0
- litlaunch/artifacts.py +79 -0
- litlaunch/backend.py +85 -0
- litlaunch/backend_start.py +393 -0
- litlaunch/browsers/__init__.py +32 -0
- litlaunch/browsers/base.py +126 -0
- litlaunch/browsers/chrome.py +97 -0
- litlaunch/browsers/default.py +93 -0
- litlaunch/browsers/edge.py +89 -0
- litlaunch/browsers/launch.py +292 -0
- litlaunch/browsers/registry.py +153 -0
- litlaunch/cli/__init__.py +5 -0
- litlaunch/cli/__main__.py +6 -0
- litlaunch/cli/commands.py +498 -0
- litlaunch/cli/common.py +105 -0
- litlaunch/cli/config.py +430 -0
- litlaunch/cli/create.py +179 -0
- litlaunch/cli/help.py +384 -0
- litlaunch/cli/inspect.py +382 -0
- litlaunch/cli/main.py +377 -0
- litlaunch/cli/preview.py +324 -0
- litlaunch/colors.py +101 -0
- litlaunch/config.py +309 -0
- litlaunch/console.py +599 -0
- litlaunch/console_style.py +76 -0
- litlaunch/diagnostics_page.py +1926 -0
- litlaunch/events.py +195 -0
- litlaunch/exceptions.py +25 -0
- litlaunch/exposure.py +254 -0
- litlaunch/governance.py +186 -0
- litlaunch/health.py +81 -0
- litlaunch/inspect/__init__.py +41 -0
- litlaunch/inspect/collect.py +680 -0
- litlaunch/inspect/models.py +140 -0
- litlaunch/inspect/render_bundle.py +50 -0
- litlaunch/inspect/render_html.py +288 -0
- litlaunch/inspect/render_json.py +16 -0
- litlaunch/inspect/streamlit_check.py +33 -0
- litlaunch/launcher.py +553 -0
- litlaunch/lifecycle.py +83 -0
- litlaunch/monitored.py +365 -0
- litlaunch/monitored_browser.py +432 -0
- litlaunch/monitored_common.py +59 -0
- litlaunch/planning.py +109 -0
- litlaunch/platforms/__init__.py +15 -0
- litlaunch/platforms/detect.py +182 -0
- litlaunch/ports.py +130 -0
- litlaunch/process.py +98 -0
- litlaunch/profiles/__init__.py +9 -0
- litlaunch/profiles/core.py +332 -0
- litlaunch/profiles/detection.py +89 -0
- litlaunch/profiles/rendering.py +207 -0
- litlaunch/profiles/state.py +107 -0
- litlaunch/profiles/wizard.py +920 -0
- litlaunch/profiles/writer.py +267 -0
- litlaunch/py.typed +1 -0
- litlaunch/redaction.py +143 -0
- litlaunch/runtime_console.py +292 -0
- litlaunch/session.py +516 -0
- litlaunch/shortcut_writer.py +479 -0
- litlaunch/shutdown.py +723 -0
- litlaunch/streamlit.py +120 -0
- litlaunch/transport.py +232 -0
- litlaunch/version.py +6 -0
- litlaunch/windowing/__init__.py +35 -0
- litlaunch/windowing/base.py +137 -0
- litlaunch/windowing/noop.py +42 -0
- litlaunch/windowing/polling.py +303 -0
- litlaunch/windowing/windows.py +302 -0
- litlaunch-1.0.0.dist-info/METADATA +594 -0
- litlaunch-1.0.0.dist-info/RECORD +76 -0
- litlaunch-1.0.0.dist-info/WHEEL +4 -0
- litlaunch-1.0.0.dist-info/entry_points.txt +2 -0
- litlaunch-1.0.0.dist-info/licenses/LICENSE +24 -0
litlaunch/__init__.py
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""Public API for LitLaunch."""
|
|
2
|
+
|
|
3
|
+
from litlaunch.backend import (
|
|
4
|
+
BackendCommand,
|
|
5
|
+
BackendCommandContext,
|
|
6
|
+
BackendCommandProvider,
|
|
7
|
+
StreamlitBackendCommandProvider,
|
|
8
|
+
)
|
|
9
|
+
from litlaunch.browsers import (
|
|
10
|
+
BrowserCapability,
|
|
11
|
+
BrowserKind,
|
|
12
|
+
BrowserLauncher,
|
|
13
|
+
BrowserLaunchResult,
|
|
14
|
+
BrowserResolution,
|
|
15
|
+
)
|
|
16
|
+
from litlaunch.colors import (
|
|
17
|
+
THEME_COLORS,
|
|
18
|
+
ThemeColor,
|
|
19
|
+
get_theme_color,
|
|
20
|
+
hook_orange,
|
|
21
|
+
is_hex_color,
|
|
22
|
+
is_theme_color_name,
|
|
23
|
+
)
|
|
24
|
+
from litlaunch.config import BrowserChoice, LauncherConfig, LaunchMode, TrustMode
|
|
25
|
+
from litlaunch.console import (
|
|
26
|
+
ConsoleMode,
|
|
27
|
+
ConsolePhase,
|
|
28
|
+
ConsoleRenderer,
|
|
29
|
+
ConsoleTheme,
|
|
30
|
+
)
|
|
31
|
+
from litlaunch.diagnostics_page import (
|
|
32
|
+
DiagnosticsPageBuilder,
|
|
33
|
+
DiagnosticsPageOptions,
|
|
34
|
+
create_diagnostics_page,
|
|
35
|
+
)
|
|
36
|
+
from litlaunch.events import (
|
|
37
|
+
RuntimeEvent,
|
|
38
|
+
RuntimeEventSink,
|
|
39
|
+
create_runtime_event_file_sink,
|
|
40
|
+
)
|
|
41
|
+
from litlaunch.exceptions import (
|
|
42
|
+
BrowserError,
|
|
43
|
+
CommandBuildError,
|
|
44
|
+
ConfigurationError,
|
|
45
|
+
LitLaunchError,
|
|
46
|
+
PortError,
|
|
47
|
+
ProcessError,
|
|
48
|
+
)
|
|
49
|
+
from litlaunch.health import HealthChecker
|
|
50
|
+
from litlaunch.inspect import (
|
|
51
|
+
DiagnosticCollector,
|
|
52
|
+
DiagnosticItem,
|
|
53
|
+
DiagnosticSection,
|
|
54
|
+
DiagnosticsReport,
|
|
55
|
+
DiagnosticStatus,
|
|
56
|
+
HTMLDiagnosticsRenderer,
|
|
57
|
+
JSONDiagnosticsRenderer,
|
|
58
|
+
SanitizedBundleRenderer,
|
|
59
|
+
)
|
|
60
|
+
from litlaunch.launcher import StreamlitLauncher
|
|
61
|
+
from litlaunch.lifecycle import LaunchEvent, LaunchPlan, LaunchResult, LaunchState
|
|
62
|
+
from litlaunch.monitored import MonitoredRunResult, run_monitored_webapp, run_profile
|
|
63
|
+
from litlaunch.platforms import (
|
|
64
|
+
Architecture,
|
|
65
|
+
OperatingSystem,
|
|
66
|
+
PlatformDetector,
|
|
67
|
+
PlatformInfo,
|
|
68
|
+
)
|
|
69
|
+
from litlaunch.ports import PortManager
|
|
70
|
+
from litlaunch.process import ManagedProcess, ProcessManager
|
|
71
|
+
from litlaunch.profiles import LaunchProfile, load_profile, load_profiles
|
|
72
|
+
from litlaunch.session import RuntimeSession
|
|
73
|
+
from litlaunch.shutdown import (
|
|
74
|
+
HookConsoleVisibility,
|
|
75
|
+
LauncherRuntime,
|
|
76
|
+
ShutdownClient,
|
|
77
|
+
ShutdownConfig,
|
|
78
|
+
ShutdownHook,
|
|
79
|
+
ShutdownHookRegistry,
|
|
80
|
+
ShutdownHookResult,
|
|
81
|
+
ShutdownHookStatus,
|
|
82
|
+
ShutdownRequestResult,
|
|
83
|
+
ShutdownResult,
|
|
84
|
+
)
|
|
85
|
+
from litlaunch.streamlit import StreamlitCommandBuilder
|
|
86
|
+
from litlaunch.version import __version__
|
|
87
|
+
from litlaunch.windowing import (
|
|
88
|
+
NoopWindowMonitor,
|
|
89
|
+
PollingWindowMonitor,
|
|
90
|
+
WindowInfo,
|
|
91
|
+
WindowMonitor,
|
|
92
|
+
WindowMonitorConfig,
|
|
93
|
+
WindowMonitorEvent,
|
|
94
|
+
WindowMonitorResult,
|
|
95
|
+
WindowMonitorStatus,
|
|
96
|
+
WindowsChromiumWindowMonitor,
|
|
97
|
+
WindowsWindowProvider,
|
|
98
|
+
WindowTarget,
|
|
99
|
+
create_window_monitor,
|
|
100
|
+
is_chromium_window,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
__all__ = [
|
|
104
|
+
"Architecture",
|
|
105
|
+
"BrowserCapability",
|
|
106
|
+
"BrowserChoice",
|
|
107
|
+
"BrowserKind",
|
|
108
|
+
"BrowserLaunchResult",
|
|
109
|
+
"BrowserLauncher",
|
|
110
|
+
"BrowserResolution",
|
|
111
|
+
"BrowserError",
|
|
112
|
+
"BackendCommand",
|
|
113
|
+
"BackendCommandContext",
|
|
114
|
+
"BackendCommandProvider",
|
|
115
|
+
"CommandBuildError",
|
|
116
|
+
"ConfigurationError",
|
|
117
|
+
"ConsoleMode",
|
|
118
|
+
"ConsolePhase",
|
|
119
|
+
"ConsoleRenderer",
|
|
120
|
+
"ConsoleTheme",
|
|
121
|
+
"get_theme_color",
|
|
122
|
+
"hook_orange",
|
|
123
|
+
"HealthChecker",
|
|
124
|
+
"HookConsoleVisibility",
|
|
125
|
+
"DiagnosticCollector",
|
|
126
|
+
"DiagnosticItem",
|
|
127
|
+
"DiagnosticSection",
|
|
128
|
+
"DiagnosticStatus",
|
|
129
|
+
"DiagnosticsPageBuilder",
|
|
130
|
+
"DiagnosticsPageOptions",
|
|
131
|
+
"DiagnosticsReport",
|
|
132
|
+
"HTMLDiagnosticsRenderer",
|
|
133
|
+
"JSONDiagnosticsRenderer",
|
|
134
|
+
"SanitizedBundleRenderer",
|
|
135
|
+
"LaunchMode",
|
|
136
|
+
"LauncherConfig",
|
|
137
|
+
"LaunchProfile",
|
|
138
|
+
"LitLaunchError",
|
|
139
|
+
"LaunchEvent",
|
|
140
|
+
"LaunchPlan",
|
|
141
|
+
"LaunchResult",
|
|
142
|
+
"LaunchState",
|
|
143
|
+
"LauncherRuntime",
|
|
144
|
+
"OperatingSystem",
|
|
145
|
+
"PlatformDetector",
|
|
146
|
+
"PlatformInfo",
|
|
147
|
+
"ManagedProcess",
|
|
148
|
+
"MonitoredRunResult",
|
|
149
|
+
"NoopWindowMonitor",
|
|
150
|
+
"PortManager",
|
|
151
|
+
"PollingWindowMonitor",
|
|
152
|
+
"PortError",
|
|
153
|
+
"ProcessError",
|
|
154
|
+
"ProcessManager",
|
|
155
|
+
"load_profile",
|
|
156
|
+
"load_profiles",
|
|
157
|
+
"RuntimeSession",
|
|
158
|
+
"RuntimeEvent",
|
|
159
|
+
"RuntimeEventSink",
|
|
160
|
+
"create_runtime_event_file_sink",
|
|
161
|
+
"run_profile",
|
|
162
|
+
"run_monitored_webapp",
|
|
163
|
+
"ShutdownClient",
|
|
164
|
+
"ShutdownConfig",
|
|
165
|
+
"ShutdownHook",
|
|
166
|
+
"ShutdownHookRegistry",
|
|
167
|
+
"ShutdownHookResult",
|
|
168
|
+
"ShutdownHookStatus",
|
|
169
|
+
"ShutdownRequestResult",
|
|
170
|
+
"ShutdownResult",
|
|
171
|
+
"StreamlitCommandBuilder",
|
|
172
|
+
"StreamlitBackendCommandProvider",
|
|
173
|
+
"StreamlitLauncher",
|
|
174
|
+
"WindowsChromiumWindowMonitor",
|
|
175
|
+
"WindowsWindowProvider",
|
|
176
|
+
"WindowInfo",
|
|
177
|
+
"WindowMonitor",
|
|
178
|
+
"WindowMonitorConfig",
|
|
179
|
+
"WindowMonitorEvent",
|
|
180
|
+
"WindowMonitorResult",
|
|
181
|
+
"WindowMonitorStatus",
|
|
182
|
+
"WindowTarget",
|
|
183
|
+
"__version__",
|
|
184
|
+
"create_diagnostics_page",
|
|
185
|
+
"create_window_monitor",
|
|
186
|
+
"is_chromium_window",
|
|
187
|
+
"is_hex_color",
|
|
188
|
+
"is_theme_color_name",
|
|
189
|
+
"THEME_COLORS",
|
|
190
|
+
"ThemeColor",
|
|
191
|
+
"TrustMode",
|
|
192
|
+
]
|
litlaunch/__main__.py
ADDED
litlaunch/_protocols.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Internal structural protocols for injectable runtime dependencies."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Protocol, runtime_checkable
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@runtime_checkable
|
|
9
|
+
class ClockProvider(Protocol):
|
|
10
|
+
"""Clock surface used for deterministic lifecycle event timestamps."""
|
|
11
|
+
|
|
12
|
+
def monotonic(self) -> float:
|
|
13
|
+
"""Return a monotonic timestamp."""
|
|
14
|
+
|
|
15
|
+
def time(self) -> float:
|
|
16
|
+
"""Return a wall-clock timestamp."""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@runtime_checkable
|
|
20
|
+
class ManagedPopen(Protocol):
|
|
21
|
+
"""Subprocess surface required by LitLaunch process ownership."""
|
|
22
|
+
|
|
23
|
+
pid: int
|
|
24
|
+
|
|
25
|
+
def poll(self) -> int | None:
|
|
26
|
+
"""Return the process return code, or None while running."""
|
|
27
|
+
|
|
28
|
+
def wait(self, timeout: float | None = None) -> int | None:
|
|
29
|
+
"""Wait for process exit and return the return code."""
|
|
30
|
+
|
|
31
|
+
def terminate(self) -> None:
|
|
32
|
+
"""Request graceful process termination."""
|
|
33
|
+
|
|
34
|
+
def kill(self) -> None:
|
|
35
|
+
"""Force process termination."""
|
litlaunch/artifacts.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Project-local generated artifact paths for LitLaunch."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import tempfile
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from litlaunch.config import LauncherConfig
|
|
9
|
+
|
|
10
|
+
ARTIFACT_DIR_NAME = ".litlaunch"
|
|
11
|
+
REPORTS_DIR_NAME = "reports"
|
|
12
|
+
SHORTCUTS_DIR_NAME = "shortcuts"
|
|
13
|
+
TMP_DIR_NAME = "tmp"
|
|
14
|
+
BROWSER_PROFILES_DIR_NAME = "browser-profiles"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def project_root_for_config(config: LauncherConfig) -> Path:
|
|
18
|
+
"""Return the project root LitLaunch should use for generated artifacts."""
|
|
19
|
+
|
|
20
|
+
if config.cwd is not None:
|
|
21
|
+
return config.cwd
|
|
22
|
+
app_parent = config.app_path.parent
|
|
23
|
+
if str(app_parent) in ("", "."):
|
|
24
|
+
return Path.cwd()
|
|
25
|
+
return app_parent
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def artifact_dir(root: Path | None = None) -> Path:
|
|
29
|
+
"""Return the root generated-artifacts directory for a project."""
|
|
30
|
+
|
|
31
|
+
return (root or Path.cwd()) / ARTIFACT_DIR_NAME
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def reports_dir(root: Path | None = None, *, create: bool = False) -> Path:
|
|
35
|
+
"""Return the reports artifact directory."""
|
|
36
|
+
|
|
37
|
+
path = artifact_dir(root) / REPORTS_DIR_NAME
|
|
38
|
+
if create:
|
|
39
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
40
|
+
return path
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def shortcuts_dir(root: Path | None = None, *, create: bool = False) -> Path:
|
|
44
|
+
"""Return the shortcut artifact directory."""
|
|
45
|
+
|
|
46
|
+
path = artifact_dir(root) / SHORTCUTS_DIR_NAME
|
|
47
|
+
if create:
|
|
48
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
49
|
+
return path
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def browser_profiles_dir(root: Path | None = None, *, create: bool = False) -> Path:
|
|
53
|
+
"""Return the managed browser-profile temp directory."""
|
|
54
|
+
|
|
55
|
+
path = artifact_dir(root) / TMP_DIR_NAME / BROWSER_PROFILES_DIR_NAME
|
|
56
|
+
if create:
|
|
57
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
58
|
+
return path
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def default_report_path(
|
|
62
|
+
root: Path | None = None, *, create_parent: bool = False
|
|
63
|
+
) -> Path:
|
|
64
|
+
"""Return the default human-readable HTML report path."""
|
|
65
|
+
|
|
66
|
+
return reports_dir(root, create=create_parent) / "litlaunch-report.html"
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def default_shortcut_path(root: Path, basename: str, extension: str) -> Path:
|
|
70
|
+
"""Return the default project-local shortcut path."""
|
|
71
|
+
|
|
72
|
+
return shortcuts_dir(root) / f"{basename}{extension}"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def create_managed_browser_profile_dir(root: Path | None = None) -> Path:
|
|
76
|
+
"""Create a project-local temporary browser profile directory."""
|
|
77
|
+
|
|
78
|
+
parent = browser_profiles_dir(root, create=True)
|
|
79
|
+
return Path(tempfile.mkdtemp(prefix="litlaunch-browser-", dir=parent))
|
litlaunch/backend.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Backend command provider abstractions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import Protocol
|
|
8
|
+
|
|
9
|
+
from litlaunch.config import LauncherConfig
|
|
10
|
+
from litlaunch.exceptions import CommandBuildError
|
|
11
|
+
from litlaunch.streamlit import StreamlitCommandBuilder
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class BackendCommandContext:
|
|
16
|
+
"""Resolved launch context passed to backend command providers."""
|
|
17
|
+
|
|
18
|
+
config: LauncherConfig
|
|
19
|
+
host: str
|
|
20
|
+
port: int
|
|
21
|
+
app_url: str
|
|
22
|
+
health_url: str
|
|
23
|
+
headless: bool
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class BackendCommand:
|
|
28
|
+
"""Shell-free command returned by a backend command provider."""
|
|
29
|
+
|
|
30
|
+
command: Sequence[str]
|
|
31
|
+
description: str = "backend"
|
|
32
|
+
backend_kind: str | None = None
|
|
33
|
+
|
|
34
|
+
def __post_init__(self) -> None:
|
|
35
|
+
if isinstance(self.command, (str, bytes)):
|
|
36
|
+
raise CommandBuildError("Backend command must be a sequence of strings.")
|
|
37
|
+
try:
|
|
38
|
+
command = tuple(str(part) for part in self.command)
|
|
39
|
+
except TypeError as exc:
|
|
40
|
+
raise CommandBuildError(
|
|
41
|
+
"Backend command must be a sequence of strings."
|
|
42
|
+
) from exc
|
|
43
|
+
if not command:
|
|
44
|
+
raise CommandBuildError("Backend command cannot be empty.")
|
|
45
|
+
if any(not part for part in command):
|
|
46
|
+
raise CommandBuildError("Backend command arguments cannot be empty.")
|
|
47
|
+
object.__setattr__(self, "command", command)
|
|
48
|
+
|
|
49
|
+
description = str(self.description).strip()
|
|
50
|
+
if not description:
|
|
51
|
+
raise CommandBuildError("Backend command description cannot be empty.")
|
|
52
|
+
object.__setattr__(self, "description", description)
|
|
53
|
+
|
|
54
|
+
if self.backend_kind is not None:
|
|
55
|
+
kind = str(self.backend_kind).strip()
|
|
56
|
+
object.__setattr__(self, "backend_kind", kind or None)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class BackendCommandProvider(Protocol):
|
|
60
|
+
"""Protocol for command-only backend customization."""
|
|
61
|
+
|
|
62
|
+
def build_backend_command(
|
|
63
|
+
self,
|
|
64
|
+
context: BackendCommandContext,
|
|
65
|
+
) -> BackendCommand:
|
|
66
|
+
"""Return the backend command LitLaunch should start."""
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class StreamlitBackendCommandProvider:
|
|
70
|
+
"""Default backend command provider for source Streamlit apps."""
|
|
71
|
+
|
|
72
|
+
description = "Streamlit backend"
|
|
73
|
+
backend_kind = "streamlit"
|
|
74
|
+
|
|
75
|
+
def build_backend_command(
|
|
76
|
+
self,
|
|
77
|
+
context: BackendCommandContext,
|
|
78
|
+
) -> BackendCommand:
|
|
79
|
+
"""Build the standard `python -m streamlit run ...` command."""
|
|
80
|
+
|
|
81
|
+
return BackendCommand(
|
|
82
|
+
command=StreamlitCommandBuilder(context.config).build(port=context.port),
|
|
83
|
+
description=self.description,
|
|
84
|
+
backend_kind=self.backend_kind,
|
|
85
|
+
)
|