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.
Files changed (76) hide show
  1. litlaunch/__init__.py +192 -0
  2. litlaunch/__main__.py +8 -0
  3. litlaunch/_protocols.py +35 -0
  4. litlaunch/artifacts.py +79 -0
  5. litlaunch/backend.py +85 -0
  6. litlaunch/backend_start.py +393 -0
  7. litlaunch/browsers/__init__.py +32 -0
  8. litlaunch/browsers/base.py +126 -0
  9. litlaunch/browsers/chrome.py +97 -0
  10. litlaunch/browsers/default.py +93 -0
  11. litlaunch/browsers/edge.py +89 -0
  12. litlaunch/browsers/launch.py +292 -0
  13. litlaunch/browsers/registry.py +153 -0
  14. litlaunch/cli/__init__.py +5 -0
  15. litlaunch/cli/__main__.py +6 -0
  16. litlaunch/cli/commands.py +498 -0
  17. litlaunch/cli/common.py +105 -0
  18. litlaunch/cli/config.py +430 -0
  19. litlaunch/cli/create.py +179 -0
  20. litlaunch/cli/help.py +384 -0
  21. litlaunch/cli/inspect.py +382 -0
  22. litlaunch/cli/main.py +377 -0
  23. litlaunch/cli/preview.py +324 -0
  24. litlaunch/colors.py +101 -0
  25. litlaunch/config.py +309 -0
  26. litlaunch/console.py +599 -0
  27. litlaunch/console_style.py +76 -0
  28. litlaunch/diagnostics_page.py +1926 -0
  29. litlaunch/events.py +195 -0
  30. litlaunch/exceptions.py +25 -0
  31. litlaunch/exposure.py +254 -0
  32. litlaunch/governance.py +186 -0
  33. litlaunch/health.py +81 -0
  34. litlaunch/inspect/__init__.py +41 -0
  35. litlaunch/inspect/collect.py +680 -0
  36. litlaunch/inspect/models.py +140 -0
  37. litlaunch/inspect/render_bundle.py +50 -0
  38. litlaunch/inspect/render_html.py +288 -0
  39. litlaunch/inspect/render_json.py +16 -0
  40. litlaunch/inspect/streamlit_check.py +33 -0
  41. litlaunch/launcher.py +553 -0
  42. litlaunch/lifecycle.py +83 -0
  43. litlaunch/monitored.py +365 -0
  44. litlaunch/monitored_browser.py +432 -0
  45. litlaunch/monitored_common.py +59 -0
  46. litlaunch/planning.py +109 -0
  47. litlaunch/platforms/__init__.py +15 -0
  48. litlaunch/platforms/detect.py +182 -0
  49. litlaunch/ports.py +130 -0
  50. litlaunch/process.py +98 -0
  51. litlaunch/profiles/__init__.py +9 -0
  52. litlaunch/profiles/core.py +332 -0
  53. litlaunch/profiles/detection.py +89 -0
  54. litlaunch/profiles/rendering.py +207 -0
  55. litlaunch/profiles/state.py +107 -0
  56. litlaunch/profiles/wizard.py +920 -0
  57. litlaunch/profiles/writer.py +267 -0
  58. litlaunch/py.typed +1 -0
  59. litlaunch/redaction.py +143 -0
  60. litlaunch/runtime_console.py +292 -0
  61. litlaunch/session.py +516 -0
  62. litlaunch/shortcut_writer.py +479 -0
  63. litlaunch/shutdown.py +723 -0
  64. litlaunch/streamlit.py +120 -0
  65. litlaunch/transport.py +232 -0
  66. litlaunch/version.py +6 -0
  67. litlaunch/windowing/__init__.py +35 -0
  68. litlaunch/windowing/base.py +137 -0
  69. litlaunch/windowing/noop.py +42 -0
  70. litlaunch/windowing/polling.py +303 -0
  71. litlaunch/windowing/windows.py +302 -0
  72. litlaunch-1.0.0.dist-info/METADATA +594 -0
  73. litlaunch-1.0.0.dist-info/RECORD +76 -0
  74. litlaunch-1.0.0.dist-info/WHEEL +4 -0
  75. litlaunch-1.0.0.dist-info/entry_points.txt +2 -0
  76. 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
@@ -0,0 +1,8 @@
1
+ """Module execution entry point for ``python -m litlaunch``."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from litlaunch.cli import main
6
+
7
+ if __name__ == "__main__": # pragma: no cover - exercised through subprocess
8
+ raise SystemExit(main())
@@ -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
+ )