lumen-app 0.4.2__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 (56) hide show
  1. lumen_app/__init__.py +7 -0
  2. lumen_app/core/__init__.py +0 -0
  3. lumen_app/core/config.py +661 -0
  4. lumen_app/core/installer.py +274 -0
  5. lumen_app/core/loader.py +45 -0
  6. lumen_app/core/router.py +87 -0
  7. lumen_app/core/server.py +389 -0
  8. lumen_app/core/service.py +49 -0
  9. lumen_app/core/tests/__init__.py +1 -0
  10. lumen_app/core/tests/test_core_integration.py +561 -0
  11. lumen_app/core/tests/test_env_checker.py +487 -0
  12. lumen_app/proto/README.md +12 -0
  13. lumen_app/proto/ml_service.proto +88 -0
  14. lumen_app/proto/ml_service_pb2.py +66 -0
  15. lumen_app/proto/ml_service_pb2.pyi +136 -0
  16. lumen_app/proto/ml_service_pb2_grpc.py +251 -0
  17. lumen_app/server.py +362 -0
  18. lumen_app/utils/env_checker.py +752 -0
  19. lumen_app/utils/installation/__init__.py +25 -0
  20. lumen_app/utils/installation/env_manager.py +152 -0
  21. lumen_app/utils/installation/micromamba_installer.py +459 -0
  22. lumen_app/utils/installation/package_installer.py +149 -0
  23. lumen_app/utils/installation/verifier.py +95 -0
  24. lumen_app/utils/logger.py +181 -0
  25. lumen_app/utils/mamba/cuda.yaml +12 -0
  26. lumen_app/utils/mamba/default.yaml +6 -0
  27. lumen_app/utils/mamba/openvino.yaml +7 -0
  28. lumen_app/utils/mamba/tensorrt.yaml +13 -0
  29. lumen_app/utils/package_resolver.py +309 -0
  30. lumen_app/utils/preset_registry.py +219 -0
  31. lumen_app/web/__init__.py +3 -0
  32. lumen_app/web/api/__init__.py +1 -0
  33. lumen_app/web/api/config.py +229 -0
  34. lumen_app/web/api/hardware.py +201 -0
  35. lumen_app/web/api/install.py +608 -0
  36. lumen_app/web/api/server.py +253 -0
  37. lumen_app/web/core/__init__.py +1 -0
  38. lumen_app/web/core/server_manager.py +348 -0
  39. lumen_app/web/core/state.py +264 -0
  40. lumen_app/web/main.py +145 -0
  41. lumen_app/web/models/__init__.py +28 -0
  42. lumen_app/web/models/config.py +63 -0
  43. lumen_app/web/models/hardware.py +64 -0
  44. lumen_app/web/models/install.py +134 -0
  45. lumen_app/web/models/server.py +95 -0
  46. lumen_app/web/static/assets/index-CGuhGHC9.css +1 -0
  47. lumen_app/web/static/assets/index-DN6HmxWS.js +56 -0
  48. lumen_app/web/static/index.html +14 -0
  49. lumen_app/web/static/vite.svg +1 -0
  50. lumen_app/web/websockets/__init__.py +1 -0
  51. lumen_app/web/websockets/logs.py +159 -0
  52. lumen_app-0.4.2.dist-info/METADATA +23 -0
  53. lumen_app-0.4.2.dist-info/RECORD +56 -0
  54. lumen_app-0.4.2.dist-info/WHEEL +5 -0
  55. lumen_app-0.4.2.dist-info/entry_points.txt +3 -0
  56. lumen_app-0.4.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,149 @@
1
+ """Lumen package installer for installing Lumen packages from GitHub Releases."""
2
+
3
+ import logging
4
+ import subprocess
5
+ from pathlib import Path
6
+ from typing import Callable
7
+
8
+ from lumen_resources.lumen_config import Region
9
+
10
+ from ...core.config import DeviceConfig
11
+ from ..package_resolver import GitHubPackageResolver, LumenPackageResolver
12
+ from .env_manager import PythonEnvManager
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class LumenPackageInstaller:
18
+ """Installs Lumen packages from GitHub Releases."""
19
+
20
+ def __init__(
21
+ self,
22
+ env_manager: PythonEnvManager,
23
+ github_resolver: GitHubPackageResolver,
24
+ log_callback: Callable[[str], None] | None = None,
25
+ ):
26
+ """Initialize package installer.
27
+
28
+ Args:
29
+ env_manager: Python environment manager
30
+ github_resolver: GitHub package resolver
31
+ log_callback: Optional callback for log messages
32
+ """
33
+ self.env_manager = env_manager
34
+ self.github_resolver = github_resolver
35
+ self.log_callback = log_callback or (lambda msg: None)
36
+
37
+ logger.debug("[LumenPackageInstaller] Initialized")
38
+
39
+ def install_packages(
40
+ self,
41
+ packages: list[str],
42
+ device_config: DeviceConfig,
43
+ region: Region,
44
+ ) -> None:
45
+ """Install Lumen packages from GitHub Releases.
46
+
47
+ Args:
48
+ packages: List of package names (e.g., ["lumen_ocr", "lumen_clip"])
49
+ device_config: Device configuration with dependency metadata
50
+ region: Region for mirror selection
51
+
52
+ Raises:
53
+ Exception: If installation fails
54
+ """
55
+ logger.info(f"[LumenPackageInstaller] Installing packages: {packages}")
56
+ self.log_callback(f"Installing {len(packages)} Lumen package(s)...")
57
+
58
+ # Create wheel download directory
59
+ cache_dir = self.env_manager.cache_dir
60
+ wheel_dir = cache_dir / "wheels"
61
+ wheel_dir.mkdir(parents=True, exist_ok=True)
62
+
63
+ # Download all wheels first and collect paths
64
+ self.log_callback("Downloading package wheels...")
65
+ wheel_paths = {} # {package_name: wheel_path}
66
+ for package in packages:
67
+ wheel_path = self._download_package_wheel(package, wheel_dir)
68
+ wheel_paths[package] = wheel_path
69
+
70
+ # Build pip install command
71
+ self.log_callback("Building installation command...")
72
+ pip_args = LumenPackageResolver.build_pip_install_args(
73
+ packages=packages,
74
+ device_config=device_config,
75
+ region=region,
76
+ wheel_paths=wheel_paths,
77
+ )
78
+
79
+ # Run pip install
80
+ self.log_callback("Running pip install...")
81
+ self._run_pip_install(pip_args)
82
+
83
+ self.log_callback("All packages installed successfully")
84
+ logger.info("[LumenPackageInstaller] All packages installed")
85
+
86
+ def _download_package_wheel(self, package: str, wheel_dir: Path) -> Path:
87
+ """Download package wheel from GitHub Releases.
88
+
89
+ Args:
90
+ package: Package name (e.g., "lumen_ocr")
91
+ wheel_dir: Directory to save wheel files
92
+
93
+ Returns:
94
+ Path to downloaded wheel
95
+
96
+ Raises:
97
+ Exception: If download fails
98
+ """
99
+ logger.debug(f"[LumenPackageInstaller] Downloading wheel for {package}")
100
+ self.log_callback(f"Downloading {package}...")
101
+
102
+ try:
103
+ url, version = self.github_resolver.resolve_package_url(package)
104
+ logger.debug(f"[LumenPackageInstaller] Resolved {package} {version}: {url}")
105
+
106
+ wheel_path = self.github_resolver.download_wheel(
107
+ url, wheel_dir, self.log_callback
108
+ )
109
+
110
+ logger.info(f"[LumenPackageInstaller] Downloaded {package}: {wheel_path}")
111
+ return wheel_path
112
+
113
+ except Exception as e:
114
+ logger.error(f"[LumenPackageInstaller] Failed to download {package}: {e}")
115
+ self.log_callback(f"Failed to download {package}: {e}")
116
+ raise Exception(f"Failed to download {package}: {e}")
117
+
118
+ def _run_pip_install(self, pip_args: list[str]) -> None:
119
+ """Run pip install command.
120
+
121
+ Args:
122
+ pip_args: Pip command arguments
123
+
124
+ Raises:
125
+ Exception: If installation fails
126
+ """
127
+ cmd_str = "pip " + " ".join(pip_args[:3]) + " ..."
128
+ logger.debug(f"[LumenPackageInstaller] Running: {cmd_str}")
129
+ self.log_callback("Running: pip install ...")
130
+
131
+ try:
132
+ result = self.env_manager.run_pip(*pip_args)
133
+
134
+ if result.returncode != 0:
135
+ error_msg = result.stderr or result.stdout
136
+ logger.error(f"[LumenPackageInstaller] Pip install failed: {error_msg}")
137
+ self.log_callback(f"Installation failed:\n{error_msg}")
138
+ raise Exception(f"Pip install failed: {error_msg}")
139
+
140
+ # Log output
141
+ if result.stdout:
142
+ logger.debug(f"[LumenPackageInstaller] Pip output:\n{result.stdout}")
143
+
144
+ logger.info("[LumenPackageInstaller] Pip install successful")
145
+
146
+ except subprocess.TimeoutExpired:
147
+ logger.error("[LumenPackageInstaller] Pip install timed out")
148
+ self.log_callback("Installation timed out")
149
+ raise Exception("Pip install timed out")
@@ -0,0 +1,95 @@
1
+ """Installation verifier for validating Lumen package installations."""
2
+
3
+ import logging
4
+ import subprocess
5
+
6
+ from .env_manager import PythonEnvManager
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class InstallationVerifier:
12
+ """Verifies Lumen package installations."""
13
+
14
+ def __init__(self, env_manager: PythonEnvManager):
15
+ """Initialize verifier.
16
+
17
+ Args:
18
+ env_manager: Python environment manager
19
+ """
20
+ self.env_manager = env_manager
21
+ logger.debug("[InstallationVerifier] Initialized")
22
+
23
+ def verify_imports(self, packages: list[str]) -> dict[str, bool]:
24
+ """Verify that packages can be imported.
25
+
26
+ Args:
27
+ packages: List of package names (e.g., ["lumen_ocr", "lumen_clip"])
28
+
29
+ Returns:
30
+ Dictionary mapping package names to import success status
31
+ """
32
+ logger.info(f"[InstallationVerifier] Verifying imports for: {packages}")
33
+ results = {}
34
+
35
+ for package in packages:
36
+ # Convert lumen-ocr to lumen_ocr
37
+ module_name = package.replace("-", "_")
38
+ success = self._verify_single_import(module_name)
39
+ results[package] = success
40
+
41
+ status = "✓" if success else "✗"
42
+ logger.info(f"[InstallationVerifier] {status} {package}")
43
+
44
+ return results
45
+
46
+ def _verify_single_import(self, module_name: str) -> bool:
47
+ """Verify that a single module can be imported.
48
+
49
+ Args:
50
+ module_name: Module name (e.g., "lumen_ocr")
51
+
52
+ Returns:
53
+ True if import successful
54
+ """
55
+ cmd = [
56
+ str(self.env_manager.micromamba_exe),
57
+ "run",
58
+ "-n",
59
+ PythonEnvManager.ENV_NAME,
60
+ "python",
61
+ "-c",
62
+ f"from {module_name} import *",
63
+ ]
64
+
65
+ logger.debug(f"[InstallationVerifier] Verifying import: {module_name}")
66
+
67
+ try:
68
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
69
+
70
+ if result.returncode == 0:
71
+ logger.debug(f"[InstallationVerifier] Import successful: {module_name}")
72
+ return True
73
+ else:
74
+ logger.warning(
75
+ f"[InstallationVerifier] Import failed for {module_name}: "
76
+ f"{result.stderr[:200]}"
77
+ )
78
+ return False
79
+
80
+ except subprocess.TimeoutExpired:
81
+ logger.error(f"[InstallationVerifier] Import timed out: {module_name}")
82
+ return False
83
+ except Exception as e:
84
+ logger.error(f"[InstallationVerifier] Import error for {module_name}: {e}")
85
+ return False
86
+
87
+ def verify_env_exists(self) -> bool:
88
+ """Verify that lumen_env exists.
89
+
90
+ Returns:
91
+ True if environment exists
92
+ """
93
+ exists = self.env_manager.env_exists()
94
+ logger.info(f"[InstallationVerifier] Environment exists: {exists}")
95
+ return exists
@@ -0,0 +1,181 @@
1
+ """Centralized logging configuration for Lumen applications.
2
+
3
+ This module provides a unified logging setup with colorized console output
4
+ and optional file logging. Usage:
5
+
6
+ from lumen_app.utils.logger import get_logger
7
+
8
+ logger = get_logger(__name__)
9
+ logger.info("Application started")
10
+
11
+ Or use the predefined loggers:
12
+
13
+ from lumen_app.utils.logger import lumen_logger
14
+
15
+ lumen_logger.info("Using predefined logger")
16
+ """
17
+
18
+ import logging
19
+ import sys
20
+ from pathlib import Path
21
+ from typing import Optional
22
+
23
+ # Try to import colorlog, fallback to standard logging
24
+ try:
25
+ import colorlog
26
+
27
+ COLORLOG_AVAILABLE = True
28
+ except ImportError:
29
+ COLORLOG_AVAILABLE = False
30
+
31
+
32
+ # Color scheme for different log levels
33
+ LOG_COLORS = {
34
+ "DEBUG": "cyan",
35
+ "INFO": "green",
36
+ "WARNING": "yellow",
37
+ "ERROR": "red",
38
+ "CRITICAL": "red,bg_white",
39
+ }
40
+
41
+ LOG_FORMAT = "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
42
+ DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
43
+
44
+
45
+ def setup_logging(
46
+ level: int = logging.INFO,
47
+ log_file: Optional[Path] = None,
48
+ enable_colors: bool = True,
49
+ ) -> None:
50
+ """Setup root logging configuration.
51
+
52
+ Args:
53
+ level: Logging level (default: INFO)
54
+ log_file: Optional path to log file
55
+ enable_colors: Whether to enable colored output (requires colorlog)
56
+ """
57
+ # Get root logger
58
+ root_logger = logging.getLogger()
59
+ root_logger.setLevel(level)
60
+
61
+ # Remove existing handlers
62
+ root_logger.handlers.clear()
63
+
64
+ # Console handler
65
+ if COLORLOG_AVAILABLE and enable_colors:
66
+ console_handler = colorlog.StreamHandler(sys.stdout)
67
+ console_formatter = colorlog.ColoredFormatter(
68
+ "%(log_color)s%(asctime)s [%(levelname)8s] %(name)s:%(reset)s %(message)s",
69
+ datefmt=DATE_FORMAT,
70
+ log_colors=LOG_COLORS,
71
+ )
72
+ else:
73
+ console_handler = logging.StreamHandler(sys.stdout)
74
+ console_formatter = logging.Formatter(LOG_FORMAT, datefmt=DATE_FORMAT)
75
+
76
+ console_handler.setFormatter(console_formatter)
77
+ console_handler.setLevel(level)
78
+ root_logger.addHandler(console_handler)
79
+
80
+ # File handler (optional)
81
+ if log_file:
82
+ log_file.parent.mkdir(parents=True, exist_ok=True)
83
+ file_handler = logging.FileHandler(log_file, encoding="utf-8")
84
+ file_formatter = logging.Formatter(LOG_FORMAT, datefmt=DATE_FORMAT)
85
+ file_handler.setFormatter(file_formatter)
86
+ file_handler.setLevel(level)
87
+ root_logger.addHandler(file_handler)
88
+
89
+ # Suppress verbose third-party loggers
90
+ _suppress_third_party_loggers()
91
+
92
+
93
+ def _suppress_third_party_loggers() -> None:
94
+ """Suppress verbose debug logging from third-party libraries."""
95
+ # List of loggers to suppress
96
+ suppressed_loggers = {
97
+ "flet": logging.WARNING,
98
+ "flet_core": logging.WARNING,
99
+ "flet.view": logging.WARNING,
100
+ "flet_web": logging.WARNING,
101
+ "flet_web.fastapi": logging.WARNING,
102
+ "httpx": logging.WARNING,
103
+ "urllib3": logging.WARNING,
104
+ "websockets": logging.WARNING,
105
+ "asyncio": logging.WARNING,
106
+ }
107
+
108
+ for logger_name, logger_level in suppressed_loggers.items():
109
+ third_party_logger = logging.getLogger(logger_name)
110
+ third_party_logger.setLevel(logger_level)
111
+
112
+
113
+ def get_logger(name: str) -> logging.Logger:
114
+ """Get a logger instance with the given name.
115
+
116
+ Args:
117
+ name: Logger name (typically __name__ from the calling module)
118
+
119
+ Returns:
120
+ Logger instance
121
+
122
+ Example:
123
+ logger = get_logger(__name__)
124
+ logger.info("Message")
125
+ """
126
+ return logging.getLogger(name)
127
+
128
+
129
+ # Predefined loggers for common modules
130
+ def _get_module_logger(module_name: str) -> logging.Logger:
131
+ """Get or create a logger for a specific module."""
132
+ logger = logging.getLogger(module_name)
133
+ # Ensure logger has a level set (root level will be used if not set)
134
+ if not logger.setLevel:
135
+ logger.setLevel(logging.DEBUG)
136
+ return logger
137
+
138
+
139
+ # Export predefined loggers
140
+ lumen_logger = _get_module_logger("lumen")
141
+ config_logger = _get_module_logger("lumen.config")
142
+ env_checker_logger = _get_module_logger("lumen.env_checker")
143
+ installer_logger = _get_module_logger("lumen.installer")
144
+ ui_logger = _get_module_logger("lumen.ui")
145
+
146
+
147
+ # Auto-setup on import (can be called explicitly if needed)
148
+ def initialize(
149
+ level: int = logging.INFO,
150
+ log_file: Optional[Path] = None,
151
+ log_dir: Optional[Path] = None,
152
+ ) -> None:
153
+ """Initialize logging system.
154
+
155
+ This is called automatically on import with default settings.
156
+ Call it explicitly to customize logging behavior.
157
+
158
+ Args:
159
+ level: Logging level (e.g., logging.DEBUG, logging.INFO)
160
+ log_file: Specific log file path
161
+ log_dir: Directory for log files (alternative to log_file)
162
+
163
+ Example:
164
+ # Initialize with DEBUG level and custom log file
165
+ initialize(
166
+ level=logging.DEBUG,
167
+ log_file=Path("~/lumen_logs/app.log")
168
+ )
169
+ """
170
+ # Determine log file path
171
+ if log_file is None and log_dir is not None:
172
+ from datetime import datetime
173
+
174
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
175
+ log_file = log_dir / f"lumen_{timestamp}.log"
176
+
177
+ setup_logging(level=level, log_file=log_file, enable_colors=COLORLOG_AVAILABLE)
178
+
179
+
180
+ # Auto-initialize with defaults
181
+ initialize(level=logging.INFO)
@@ -0,0 +1,12 @@
1
+ name: lumen_env
2
+ channels:
3
+ - nvidia
4
+ - conda-forge
5
+ - defaults
6
+ dependencies:
7
+ - python=3.11
8
+ - pip
9
+ - cuda-version=12.6
10
+ - cuda-toolkit
11
+ - cudnn
12
+ - cutensor
@@ -0,0 +1,6 @@
1
+ name: lumen_env
2
+ channels:
3
+ - conda-forge
4
+ dependencies:
5
+ - python=3.11
6
+ - uv
@@ -0,0 +1,7 @@
1
+ name: lumen_env
2
+ channels:
3
+ - conda-forge
4
+ dependencies:
5
+ - python=3.11
6
+ - openvino=2025.3.0
7
+ - pip
@@ -0,0 +1,13 @@
1
+ name: lumen_env
2
+ channels:
3
+ - nvidia
4
+ - conda-forge
5
+ - defaults
6
+ dependencies:
7
+ - python=3.11
8
+ - pip
9
+ - cuda-version=12.6
10
+ - cuda-toolkit
11
+ - cudnn
12
+ - cutensor
13
+ - tensorrt