mcli-framework 7.12.0__py3-none-any.whl → 7.12.3__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.

Potentially problematic release.


This version of mcli-framework might be problematic. Click here for more details.

Files changed (216) hide show
  1. mcli/app/__init__.py +0 -2
  2. mcli/app/commands_cmd.py +19 -23
  3. mcli/app/completion_helpers.py +5 -5
  4. mcli/app/init_cmd.py +10 -10
  5. mcli/app/lock_cmd.py +82 -27
  6. mcli/app/main.py +4 -50
  7. mcli/app/model/model.py +5 -10
  8. mcli/app/store_cmd.py +8 -8
  9. mcli/app/video/__init__.py +0 -2
  10. mcli/app/video/video.py +1 -14
  11. mcli/chat/chat.py +90 -108
  12. mcli/chat/command_rag.py +0 -4
  13. mcli/chat/enhanced_chat.py +32 -41
  14. mcli/chat/system_controller.py +37 -37
  15. mcli/chat/system_integration.py +4 -5
  16. mcli/cli.py +2 -3
  17. mcli/lib/api/api.py +4 -9
  18. mcli/lib/api/daemon_client.py +19 -20
  19. mcli/lib/api/daemon_client_local.py +1 -3
  20. mcli/lib/api/daemon_decorator.py +6 -6
  21. mcli/lib/api/mcli_decorators.py +4 -8
  22. mcli/lib/auth/__init__.py +0 -1
  23. mcli/lib/auth/auth.py +4 -5
  24. mcli/lib/auth/mcli_manager.py +7 -12
  25. mcli/lib/auth/token_util.py +5 -5
  26. mcli/lib/config/__init__.py +29 -1
  27. mcli/lib/config/config.py +0 -1
  28. mcli/lib/custom_commands.py +1 -1
  29. mcli/lib/discovery/command_discovery.py +15 -15
  30. mcli/lib/erd/erd.py +7 -7
  31. mcli/lib/files/files.py +1 -1
  32. mcli/lib/fs/__init__.py +31 -1
  33. mcli/lib/fs/fs.py +12 -13
  34. mcli/lib/lib.py +0 -1
  35. mcli/lib/logger/logger.py +7 -10
  36. mcli/lib/performance/optimizer.py +25 -27
  37. mcli/lib/performance/rust_bridge.py +22 -27
  38. mcli/lib/performance/uvloop_config.py +0 -1
  39. mcli/lib/pickles/__init__.py +0 -1
  40. mcli/lib/pickles/pickles.py +0 -2
  41. mcli/lib/secrets/commands.py +0 -2
  42. mcli/lib/secrets/manager.py +0 -1
  43. mcli/lib/secrets/repl.py +2 -3
  44. mcli/lib/secrets/store.py +1 -2
  45. mcli/lib/services/data_pipeline.py +34 -34
  46. mcli/lib/services/lsh_client.py +38 -40
  47. mcli/lib/shell/shell.py +2 -2
  48. mcli/lib/toml/__init__.py +0 -1
  49. mcli/lib/ui/styling.py +0 -1
  50. mcli/lib/ui/visual_effects.py +33 -41
  51. mcli/lib/watcher/watcher.py +0 -1
  52. mcli/ml/__init__.py +1 -1
  53. mcli/ml/api/__init__.py +1 -1
  54. mcli/ml/api/app.py +8 -9
  55. mcli/ml/api/middleware.py +10 -10
  56. mcli/ml/api/routers/__init__.py +1 -1
  57. mcli/ml/api/routers/admin_router.py +3 -3
  58. mcli/ml/api/routers/auth_router.py +17 -18
  59. mcli/ml/api/routers/backtest_router.py +2 -2
  60. mcli/ml/api/routers/data_router.py +2 -2
  61. mcli/ml/api/routers/model_router.py +14 -15
  62. mcli/ml/api/routers/monitoring_router.py +2 -2
  63. mcli/ml/api/routers/portfolio_router.py +2 -2
  64. mcli/ml/api/routers/prediction_router.py +10 -9
  65. mcli/ml/api/routers/trade_router.py +2 -2
  66. mcli/ml/api/routers/websocket_router.py +6 -7
  67. mcli/ml/api/schemas.py +2 -2
  68. mcli/ml/auth/__init__.py +1 -1
  69. mcli/ml/auth/auth_manager.py +22 -23
  70. mcli/ml/auth/models.py +17 -17
  71. mcli/ml/auth/permissions.py +17 -17
  72. mcli/ml/backtesting/__init__.py +1 -1
  73. mcli/ml/backtesting/backtest_engine.py +31 -35
  74. mcli/ml/backtesting/performance_metrics.py +12 -14
  75. mcli/ml/backtesting/run.py +1 -2
  76. mcli/ml/cache.py +35 -36
  77. mcli/ml/cli/__init__.py +1 -1
  78. mcli/ml/cli/main.py +21 -24
  79. mcli/ml/config/__init__.py +1 -1
  80. mcli/ml/config/settings.py +28 -29
  81. mcli/ml/configs/__init__.py +1 -1
  82. mcli/ml/configs/dvc_config.py +14 -15
  83. mcli/ml/configs/mlflow_config.py +12 -13
  84. mcli/ml/configs/mlops_manager.py +19 -21
  85. mcli/ml/dashboard/__init__.py +4 -4
  86. mcli/ml/dashboard/app.py +20 -30
  87. mcli/ml/dashboard/app_supabase.py +16 -19
  88. mcli/ml/dashboard/app_training.py +11 -14
  89. mcli/ml/dashboard/cli.py +2 -2
  90. mcli/ml/dashboard/common.py +2 -3
  91. mcli/ml/dashboard/components/__init__.py +1 -1
  92. mcli/ml/dashboard/components/charts.py +13 -11
  93. mcli/ml/dashboard/components/metrics.py +7 -7
  94. mcli/ml/dashboard/components/tables.py +12 -9
  95. mcli/ml/dashboard/overview.py +2 -2
  96. mcli/ml/dashboard/pages/__init__.py +1 -1
  97. mcli/ml/dashboard/pages/cicd.py +15 -18
  98. mcli/ml/dashboard/pages/debug_dependencies.py +7 -7
  99. mcli/ml/dashboard/pages/monte_carlo_predictions.py +11 -18
  100. mcli/ml/dashboard/pages/predictions_enhanced.py +24 -32
  101. mcli/ml/dashboard/pages/scrapers_and_logs.py +22 -24
  102. mcli/ml/dashboard/pages/test_portfolio.py +3 -6
  103. mcli/ml/dashboard/pages/trading.py +16 -18
  104. mcli/ml/dashboard/pages/workflows.py +20 -30
  105. mcli/ml/dashboard/utils.py +9 -9
  106. mcli/ml/dashboard/warning_suppression.py +3 -3
  107. mcli/ml/data_ingestion/__init__.py +1 -1
  108. mcli/ml/data_ingestion/api_connectors.py +41 -46
  109. mcli/ml/data_ingestion/data_pipeline.py +36 -46
  110. mcli/ml/data_ingestion/stream_processor.py +43 -46
  111. mcli/ml/database/__init__.py +1 -1
  112. mcli/ml/database/migrations/env.py +2 -2
  113. mcli/ml/database/models.py +22 -24
  114. mcli/ml/database/session.py +14 -14
  115. mcli/ml/experimentation/__init__.py +1 -1
  116. mcli/ml/experimentation/ab_testing.py +45 -46
  117. mcli/ml/features/__init__.py +1 -1
  118. mcli/ml/features/ensemble_features.py +22 -27
  119. mcli/ml/features/recommendation_engine.py +30 -30
  120. mcli/ml/features/stock_features.py +29 -32
  121. mcli/ml/features/test_feature_engineering.py +10 -11
  122. mcli/ml/logging.py +4 -4
  123. mcli/ml/mlops/__init__.py +1 -1
  124. mcli/ml/mlops/data_versioning.py +29 -30
  125. mcli/ml/mlops/experiment_tracker.py +24 -24
  126. mcli/ml/mlops/model_serving.py +31 -34
  127. mcli/ml/mlops/pipeline_orchestrator.py +27 -35
  128. mcli/ml/models/__init__.py +5 -6
  129. mcli/ml/models/base_models.py +23 -23
  130. mcli/ml/models/ensemble_models.py +31 -31
  131. mcli/ml/models/recommendation_models.py +18 -19
  132. mcli/ml/models/test_models.py +14 -16
  133. mcli/ml/monitoring/__init__.py +1 -1
  134. mcli/ml/monitoring/drift_detection.py +32 -36
  135. mcli/ml/monitoring/metrics.py +2 -2
  136. mcli/ml/optimization/__init__.py +1 -1
  137. mcli/ml/optimization/optimize.py +1 -2
  138. mcli/ml/optimization/portfolio_optimizer.py +30 -32
  139. mcli/ml/predictions/__init__.py +1 -1
  140. mcli/ml/preprocessing/__init__.py +1 -1
  141. mcli/ml/preprocessing/data_cleaners.py +22 -23
  142. mcli/ml/preprocessing/feature_extractors.py +23 -26
  143. mcli/ml/preprocessing/ml_pipeline.py +23 -23
  144. mcli/ml/preprocessing/test_preprocessing.py +7 -8
  145. mcli/ml/scripts/populate_sample_data.py +0 -4
  146. mcli/ml/serving/serve.py +1 -2
  147. mcli/ml/tasks.py +17 -17
  148. mcli/ml/tests/test_integration.py +29 -30
  149. mcli/ml/tests/test_training_dashboard.py +21 -21
  150. mcli/ml/trading/__init__.py +1 -1
  151. mcli/ml/trading/migrations.py +5 -5
  152. mcli/ml/trading/models.py +21 -23
  153. mcli/ml/trading/paper_trading.py +16 -13
  154. mcli/ml/trading/risk_management.py +17 -18
  155. mcli/ml/trading/trading_service.py +25 -28
  156. mcli/ml/training/__init__.py +1 -1
  157. mcli/ml/training/train.py +0 -1
  158. mcli/public/oi/oi.py +1 -2
  159. mcli/self/completion_cmd.py +6 -10
  160. mcli/self/logs_cmd.py +19 -24
  161. mcli/self/migrate_cmd.py +22 -20
  162. mcli/self/redis_cmd.py +10 -11
  163. mcli/self/self_cmd.py +62 -18
  164. mcli/self/store_cmd.py +10 -12
  165. mcli/self/visual_cmd.py +9 -14
  166. mcli/self/zsh_cmd.py +2 -4
  167. mcli/workflow/daemon/async_command_database.py +23 -24
  168. mcli/workflow/daemon/async_process_manager.py +27 -29
  169. mcli/workflow/daemon/client.py +27 -33
  170. mcli/workflow/daemon/daemon.py +32 -36
  171. mcli/workflow/daemon/enhanced_daemon.py +24 -33
  172. mcli/workflow/daemon/process_cli.py +11 -12
  173. mcli/workflow/daemon/process_manager.py +23 -26
  174. mcli/workflow/daemon/test_daemon.py +4 -5
  175. mcli/workflow/dashboard/dashboard_cmd.py +0 -1
  176. mcli/workflow/doc_convert.py +15 -17
  177. mcli/workflow/gcloud/__init__.py +0 -1
  178. mcli/workflow/gcloud/gcloud.py +11 -8
  179. mcli/workflow/git_commit/ai_service.py +14 -15
  180. mcli/workflow/lsh_integration.py +9 -11
  181. mcli/workflow/model_service/client.py +26 -31
  182. mcli/workflow/model_service/download_and_run_efficient_models.py +10 -14
  183. mcli/workflow/model_service/lightweight_embedder.py +25 -35
  184. mcli/workflow/model_service/lightweight_model_server.py +26 -32
  185. mcli/workflow/model_service/lightweight_test.py +7 -10
  186. mcli/workflow/model_service/model_service.py +80 -91
  187. mcli/workflow/model_service/ollama_efficient_runner.py +14 -18
  188. mcli/workflow/model_service/openai_adapter.py +23 -23
  189. mcli/workflow/model_service/pdf_processor.py +21 -26
  190. mcli/workflow/model_service/test_efficient_runner.py +12 -16
  191. mcli/workflow/model_service/test_example.py +11 -13
  192. mcli/workflow/model_service/test_integration.py +3 -5
  193. mcli/workflow/model_service/test_new_features.py +7 -8
  194. mcli/workflow/notebook/converter.py +1 -1
  195. mcli/workflow/notebook/notebook_cmd.py +5 -6
  196. mcli/workflow/notebook/schema.py +0 -1
  197. mcli/workflow/notebook/validator.py +7 -3
  198. mcli/workflow/openai/openai.py +1 -2
  199. mcli/workflow/registry/registry.py +4 -1
  200. mcli/workflow/repo/repo.py +6 -7
  201. mcli/workflow/scheduler/cron_parser.py +16 -19
  202. mcli/workflow/scheduler/job.py +10 -10
  203. mcli/workflow/scheduler/monitor.py +15 -15
  204. mcli/workflow/scheduler/persistence.py +17 -18
  205. mcli/workflow/scheduler/scheduler.py +37 -38
  206. mcli/workflow/secrets/__init__.py +1 -1
  207. mcli/workflow/sync/test_cmd.py +0 -1
  208. mcli/workflow/wakatime/__init__.py +5 -9
  209. mcli/workflow/wakatime/wakatime.py +1 -2
  210. {mcli_framework-7.12.0.dist-info → mcli_framework-7.12.3.dist-info}/METADATA +1 -1
  211. mcli_framework-7.12.3.dist-info/RECORD +279 -0
  212. mcli_framework-7.12.0.dist-info/RECORD +0 -279
  213. {mcli_framework-7.12.0.dist-info → mcli_framework-7.12.3.dist-info}/WHEEL +0 -0
  214. {mcli_framework-7.12.0.dist-info → mcli_framework-7.12.3.dist-info}/entry_points.txt +0 -0
  215. {mcli_framework-7.12.0.dist-info → mcli_framework-7.12.3.dist-info}/licenses/LICENSE +0 -0
  216. {mcli_framework-7.12.0.dist-info → mcli_framework-7.12.3.dist-info}/top_level.txt +0 -0
mcli/lib/api/api.py CHANGED
@@ -1,20 +1,15 @@
1
1
  import functools
2
2
  import inspect
3
- import json
4
3
  import os
5
4
  import random
6
5
  import socket
7
- import sys
8
6
  import threading
9
7
  import time
10
- from contextlib import asynccontextmanager
11
8
  from pathlib import Path
12
9
  from typing import Any, Callable, Dict, List, Optional, Union
13
10
 
14
- import click
15
- import requests
16
11
  import uvicorn
17
- from fastapi import FastAPI, HTTPException, Request
12
+ from fastapi import FastAPI
18
13
  from fastapi.middleware.cors import CORSMiddleware
19
14
  from pydantic import BaseModel, Field
20
15
 
@@ -228,7 +223,7 @@ class ClickToAPIDecorator:
228
223
  fields = {}
229
224
 
230
225
  for param_name, param in sig.parameters.items():
231
- if param_name in ["self", "ctx"]:
226
+ if param_name in ["sel", "ctx"]:
232
227
  continue
233
228
 
234
229
  # Get parameter type and default
@@ -243,7 +238,7 @@ class ClickToAPIDecorator:
243
238
  # Handle boolean flags
244
239
  param_type = bool
245
240
  elif param_type in [int, float]:
246
- param_type = param_type
241
+ param_type = param_type # noqa: SIM909
247
242
  else:
248
243
  param_type = str
249
244
 
@@ -544,7 +539,7 @@ def register_command_as_api(
544
539
  logger.debug("API app not available, skipping endpoint registration")
545
540
  return
546
541
 
547
- logger.info(f"API app available, proceeding with registration")
542
+ logger.info("API app available, proceeding with registration")
548
543
 
549
544
  decorator = ClickToAPIDecorator(
550
545
  endpoint_path=endpoint_path,
@@ -1,4 +1,3 @@
1
- import json
2
1
  import time
3
2
  from dataclasses import dataclass
4
3
  from pathlib import Path
@@ -14,7 +13,7 @@ logger = get_logger(__name__)
14
13
 
15
14
  @dataclass
16
15
  class DaemonClientConfig:
17
- """Configuration for daemon client"""
16
+ """Configuration for daemon client."""
18
17
 
19
18
  host: str = "localhost"
20
19
  port: int = 8000
@@ -24,7 +23,7 @@ class DaemonClientConfig:
24
23
 
25
24
 
26
25
  class APIDaemonClient:
27
- """Client for interacting with the MCLI API Daemon or Flask shell daemon"""
26
+ """Client for interacting with the MCLI API Daemon or Flask shell daemon."""
28
27
 
29
28
  def __init__(self, config: Optional[DaemonClientConfig] = None, shell_mode: bool = False):
30
29
  self.config = config or self._load_config()
@@ -37,8 +36,8 @@ class APIDaemonClient:
37
36
  self.session = requests.Session()
38
37
 
39
38
  def execute_shell_command(self, command: str) -> Dict[str, Any]:
40
- """Execute a raw shell command via the Flask test server"""
41
- url = f"http://localhost:5005/execute"
39
+ """Execute a raw shell command via the Flask test server."""
40
+ url = "http://localhost:5005/execute"
42
41
  try:
43
42
  response = self.session.post(
44
43
  url, json={"command": command}, timeout=self.config.timeout
@@ -49,7 +48,7 @@ class APIDaemonClient:
49
48
  raise Exception(f"Failed to connect to Flask shell daemon at {url}: {e}")
50
49
 
51
50
  def _load_config(self) -> DaemonClientConfig:
52
- """Load configuration from config files"""
51
+ """Load configuration from config files."""
53
52
  config = DaemonClientConfig()
54
53
 
55
54
  # Try to load from config.toml files
@@ -83,7 +82,7 @@ class APIDaemonClient:
83
82
  params: Optional[Dict] = None,
84
83
  **kwargs,
85
84
  ) -> Dict[str, Any]:
86
- """Make HTTP request to daemon with retry logic"""
85
+ """Make HTTP request to daemon with retry logic."""
87
86
  url = f"{self.base_url}{endpoint}"
88
87
  for attempt in range(self.config.retry_attempts):
89
88
  try:
@@ -107,11 +106,11 @@ class APIDaemonClient:
107
106
  return {} # Always return a dict
108
107
 
109
108
  def health_check(self) -> Dict[str, Any]:
110
- """Check daemon health"""
109
+ """Check daemon health."""
111
110
  return self._make_request("GET", "/health")
112
111
 
113
112
  def status(self) -> Dict[str, Any]:
114
- """Get daemon status"""
113
+ """Get daemon status."""
115
114
  return self._make_request("GET", "/status")
116
115
 
117
116
  def list_commands(self, all: bool = False) -> Dict[str, Any]:
@@ -120,7 +119,7 @@ class APIDaemonClient:
120
119
  return self._make_request("GET", "/commands", params=params)
121
120
 
122
121
  def get_command_details(self, command_id: str) -> Optional[Dict[str, Any]]:
123
- """Get detailed information about a specific command"""
122
+ """Get detailed information about a specific command."""
124
123
  return self._make_request("GET", f"/commands/{command_id}")
125
124
 
126
125
  def execute_command(
@@ -130,7 +129,7 @@ class APIDaemonClient:
130
129
  args: Optional[List[str]] = None,
131
130
  timeout: Optional[int] = None,
132
131
  ) -> Dict[str, Any]:
133
- """Execute a command via the daemon"""
132
+ """Execute a command via the daemon."""
134
133
  if not command_id and not command_name:
135
134
  raise ValueError("Either command_id or command_name must be provided")
136
135
 
@@ -146,15 +145,15 @@ class APIDaemonClient:
146
145
  return self._make_request("POST", "/execute", data=data)
147
146
 
148
147
  def start_daemon(self) -> Dict[str, Any]:
149
- """Start the daemon via HTTP"""
148
+ """Start the daemon via HTTP."""
150
149
  return self._make_request("POST", "/daemon/start")
151
150
 
152
151
  def stop_daemon(self) -> Dict[str, Any]:
153
- """Stop the daemon via HTTP"""
152
+ """Stop the daemon via HTTP."""
154
153
  return self._make_request("POST", "/daemon/stop")
155
154
 
156
155
  def is_running(self) -> bool:
157
- """Check if daemon is running"""
156
+ """Check if daemon is running."""
158
157
  try:
159
158
  status = self.status()
160
159
  return status.get("running", False)
@@ -162,7 +161,7 @@ class APIDaemonClient:
162
161
  return False
163
162
 
164
163
  def wait_for_daemon(self, timeout: int = 30) -> bool:
165
- """Wait for daemon to be ready"""
164
+ """Wait for daemon to be ready."""
166
165
  start_time = time.time()
167
166
  while time.time() - start_time < timeout:
168
167
  if self.is_running():
@@ -173,31 +172,31 @@ class APIDaemonClient:
173
172
 
174
173
  # Convenience functions for easy usage
175
174
  def execute_shell_command_via_flask(command: str) -> Dict[str, Any]:
176
- """Execute a raw shell command via the Flask test server (convenience function)"""
175
+ """Execute a raw shell command via the Flask test server (convenience function)."""
177
176
  client = APIDaemonClient(shell_mode=True)
178
177
  return client.execute_shell_command(command)
179
178
 
180
179
 
181
180
  def get_daemon_client() -> APIDaemonClient:
182
- """Get a configured daemon client"""
181
+ """Get a configured daemon client."""
183
182
  return APIDaemonClient()
184
183
 
185
184
 
186
185
  def execute_command_via_daemon(
187
186
  command_name: str, args: Optional[List[str]] = None
188
187
  ) -> Dict[str, Any]:
189
- """Execute a command via the daemon (convenience function)"""
188
+ """Execute a command via the daemon (convenience function)."""
190
189
  client = get_daemon_client()
191
190
  return client.execute_command(command_name=command_name, args=args)
192
191
 
193
192
 
194
193
  def check_daemon_status() -> Dict[str, Any]:
195
- """Check daemon status (convenience function)"""
194
+ """Check daemon status (convenience function)."""
196
195
  client = get_daemon_client()
197
196
  return client.status()
198
197
 
199
198
 
200
199
  def list_available_commands() -> Dict[str, Any]:
201
- """List available commands (convenience function)"""
200
+ """List available commands (convenience function)."""
202
201
  client = get_daemon_client()
203
202
  return client.list_commands()
@@ -1,16 +1,14 @@
1
1
  import json
2
2
  import subprocess
3
- from pathlib import Path
4
3
  from typing import Any, Dict, List, Optional
5
4
 
6
5
  from mcli.lib.logger.logger import get_logger
7
- from mcli.lib.toml.toml import read_from_toml
8
6
 
9
7
  logger = get_logger(__name__)
10
8
 
11
9
 
12
10
  class LocalDaemonClient:
13
- """Client for interacting with the MCLI Daemon via CLI subprocess (local IPC)"""
11
+ """Client for interacting with the MCLI Daemon via CLI subprocess (local IPC)."""
14
12
 
15
13
  def __init__(self):
16
14
  self.daemon_cmd = ["python", "-m", "mcli.workflow.daemon.daemon"]
@@ -7,7 +7,7 @@ from typing import Any, Callable, Dict, List, Optional
7
7
  from mcli.lib.logger.logger import get_logger
8
8
  from mcli.lib.toml.toml import read_from_toml
9
9
 
10
- from .daemon_client import APIDaemonClient, get_daemon_client
10
+ from .daemon_client import get_daemon_client
11
11
 
12
12
  logger = get_logger(__name__)
13
13
 
@@ -77,7 +77,7 @@ def daemon_command(
77
77
 
78
78
 
79
79
  def _is_daemon_routing_enabled() -> bool:
80
- """Check if daemon routing is enabled in configuration"""
80
+ """Check if daemon routing is enabled in configuration."""
81
81
  # Check environment variable
82
82
  if os.environ.get("MCLI_DAEMON_ROUTING", "false").lower() in ("true", "1", "yes"):
83
83
  return True
@@ -102,7 +102,7 @@ def _is_daemon_routing_enabled() -> bool:
102
102
 
103
103
 
104
104
  def _convert_to_command_args(args: tuple, kwargs: dict, func: Callable) -> List[str]:
105
- """Convert function arguments to command line arguments"""
105
+ """Convert function arguments to command line arguments."""
106
106
  cmd_args = []
107
107
 
108
108
  # Get function signature
@@ -140,7 +140,7 @@ def _convert_to_command_args(args: tuple, kwargs: dict, func: Callable) -> List[
140
140
  # *args
141
141
  if isinstance(param_value, (list, tuple)):
142
142
  cmd_args.extend([str(arg) for arg in param_value])
143
- elif param.kind == inspect.Parameter.VAR_KEYWORD:
143
+ elif param.kind == inspect.Parameter.VAR_KEYWORD: # noqa: SIM102
144
144
  # **kwargs
145
145
  if isinstance(param_value, dict):
146
146
  for key, value in param_value.items():
@@ -199,7 +199,7 @@ def daemon_group(
199
199
 
200
200
  # Convenience function to check if daemon is available
201
201
  def is_daemon_available() -> bool:
202
- """Check if the API daemon is available and running"""
202
+ """Check if the API daemon is available and running."""
203
203
  try:
204
204
  client = get_daemon_client()
205
205
  return client.is_running()
@@ -209,7 +209,7 @@ def is_daemon_available() -> bool:
209
209
 
210
210
  # Convenience function to get daemon status
211
211
  def get_daemon_status() -> Optional[Dict[str, Any]]:
212
- """Get daemon status if available"""
212
+ """Get daemon status if available."""
213
213
  try:
214
214
  client = get_daemon_client()
215
215
  return client.status()
@@ -6,17 +6,13 @@ adding API endpoints and background processing capabilities while maintaining
6
6
  the familiar Click interface. Users only need to import mcli and get everything.
7
7
  """
8
8
 
9
- import functools
10
- import inspect
11
9
  import os
12
10
  import time
13
- from pathlib import Path
14
11
  from typing import Any, Callable, Dict, List, Optional, Union
15
12
 
16
13
  import click
17
14
 
18
15
  from mcli.lib.logger.logger import get_logger
19
- from mcli.lib.toml.toml import read_from_toml
20
16
 
21
17
  from .api import api_endpoint as _api_endpoint
22
18
  from .api import get_api_app, start_api_server, stop_api_server
@@ -590,7 +586,7 @@ def get_network_credentials():
590
586
 
591
587
  # Re-export Click types and classes
592
588
  def _get_click_types():
593
- """Get Click types for re-export"""
589
+ """Get Click types for re-export."""
594
590
  import click
595
591
 
596
592
  return {
@@ -950,14 +946,14 @@ def status_check():
950
946
 
951
947
 
952
948
  class ChatCommandGroup(click.Group):
953
- """Special command group that provides chat-based interaction"""
949
+ """Special command group that provides chat-based interaction."""
954
950
 
955
951
  def __init__(self, *args, **kwargs):
956
952
  super().__init__(*args, **kwargs)
957
953
  self.chat_client = None
958
954
 
959
955
  def get_help(self, ctx):
960
- """Start interactive chat session instead of showing normal help"""
956
+ """Start interactive chat session instead of showing normal help."""
961
957
  from mcli.chat.chat import ChatClient
962
958
 
963
959
  self.chat_client = ChatClient()
@@ -969,7 +965,7 @@ from typing import Any, Callable
969
965
 
970
966
 
971
967
  def chat(**kwargs) -> Callable[[Callable[..., Any]], click.Group]:
972
- """Create a chat command group that provides an interactive LLM-powered interface"""
968
+ """Create a chat command group that provides an interactive LLM-powered interface."""
973
969
  kwargs.setdefault("invoke_without_command", True)
974
970
  kwargs.setdefault("no_args_is_help", False)
975
971
  return click.group(cls=ChatCommandGroup, **kwargs)
mcli/lib/auth/__init__.py CHANGED
@@ -1 +0,0 @@
1
- from .auth import *
mcli/lib/auth/auth.py CHANGED
@@ -6,7 +6,7 @@ from .token_manager import TokenManager
6
6
 
7
7
 
8
8
  def configure():
9
- """Configure authentication token"""
9
+ """Configure authentication token."""
10
10
  token_manager = TokenManager()
11
11
 
12
12
  # Prompt for token, hiding input
@@ -25,7 +25,7 @@ def configure():
25
25
 
26
26
 
27
27
  def show_token():
28
- """Display the current authentication token"""
28
+ """Display the current authentication token."""
29
29
  token_manager = TokenManager()
30
30
  token = token_manager.get_token()
31
31
 
@@ -36,7 +36,7 @@ def show_token():
36
36
 
37
37
 
38
38
  def clear_token():
39
- """Clear the stored authentication token"""
39
+ """Clear the stored authentication token."""
40
40
  token_manager = TokenManager()
41
41
 
42
42
  if click.confirm("Are you sure you want to clear the stored token?"):
@@ -77,8 +77,7 @@ def get_mcli_basic_auth() -> Optional[str]:
77
77
 
78
78
  @click.group(name="auth")
79
79
  def auth():
80
- """Authentication commands"""
81
- pass
80
+ """Authentication commands."""
82
81
 
83
82
 
84
83
  if __name__ == "__main__":
@@ -1,11 +1,6 @@
1
1
  import base64
2
- import json
3
- import time
4
- from pathlib import Path
5
2
  from urllib.request import urlopen
6
3
 
7
- import click
8
-
9
4
  from mcli.lib.logger.logger import get_logger
10
5
 
11
6
  logger = get_logger(__name__)
@@ -20,24 +15,24 @@ class MCLIManager:
20
15
  self.env_url = env_url
21
16
 
22
17
  def create_mcli_basic_auth_token(self):
23
- """Create a basic auth token for MCLI authentication"""
18
+ """Create a basic auth token for MCLI authentication."""
24
19
  basic_content_bytes = "BA:BA".encode("ASCII")
25
20
  basic_token_b64 = base64.b64encode(basic_content_bytes).decode("ASCII")
26
21
  return basic_token_b64
27
22
 
28
23
  def create_mcli_basic_auth_header(self, token: str):
29
- """Create a basic auth header for MCLI authentication"""
24
+ """Create a basic auth header for MCLI authentication."""
30
25
  return "Basic " + token
31
26
 
32
27
  def mcli_as_dev_user(self, url, authHeader):
33
- """Connect to MCLI as a dev user"""
28
+ """Connect to MCLI as a dev user."""
34
29
  src = urlopen(url + "/remote/mcli.py").read()
35
30
  exec_scope = {}
36
31
  exec(src, exec_scope)
37
32
  return exec_scope["get_mcli"](url=url, authz=authHeader)
38
33
 
39
34
  def mcli_as_basic_user(self):
40
- """Connect to MCLI as a BA user"""
35
+ """Connect to MCLI as a BA user."""
41
36
  url = self.env_url
42
37
  token = self.create_mcli_basic_auth_token()
43
38
  basicAuthHeader = self.create_mcli_basic_auth_header(token)
@@ -46,7 +41,7 @@ class MCLIManager:
46
41
 
47
42
 
48
43
  class MCLIConnectionParams:
49
- """A picklable class to store MCLI connection parameters"""
44
+ """A picklable class to store MCLI connection parameters."""
50
45
 
51
46
  def __init__(self, url, auth_token):
52
47
  self.url = url
@@ -60,7 +55,7 @@ class MCLIInstance:
60
55
  self._mcli = self._initialize_mcli()
61
56
 
62
57
  def _normalize_url(self, url):
63
- """Normalize URL to ensure it's properly formatted"""
58
+ """Normalize URL to ensure it's properly formatted."""
64
59
  if not url:
65
60
  raise ValueError("URL cannot be empty")
66
61
 
@@ -71,7 +66,7 @@ class MCLIInstance:
71
66
  return url.rstrip("/")
72
67
 
73
68
  def _initialize_mcli(self):
74
- """Initialize the MCLI connection"""
69
+ """Initialize the MCLI connection."""
75
70
  mcli_url = f"{self.url}/remote/mcli.py"
76
71
 
77
72
  try:
@@ -69,7 +69,7 @@ def execute(action, args):
69
69
 
70
70
  elif action == "PROVISION_THIRDPARTY":
71
71
  ensure_directory_exists(DEV_SECRETS_ROOT + "thirdParty")
72
- mcli = mcli_as_basic_user()
72
+ mcli = mcli_as_basic_user() # noqa: F841
73
73
 
74
74
  else:
75
75
  help(action, args)
@@ -759,7 +759,7 @@ def get_current_version(file_path=VERSION_FILE_PATH):
759
759
  logger.info(f"Error reading file {file_path}: {e}")
760
760
  return None
761
761
 
762
- if version == None:
762
+ if version is None:
763
763
  raise ValueError(f"File '{file_path}' does not contain version.")
764
764
  elif is_major_minor_patch(version):
765
765
  return version
@@ -866,7 +866,7 @@ def align_version(
866
866
  for key in platform_pkgs:
867
867
  if key in data[K_DEPS]:
868
868
  val = data[K_DEPS][key]
869
- if val == None or val != maj_min:
869
+ if val is None or val != maj_min:
870
870
  data[K_DEPS][key] = maj_min
871
871
  modified = True
872
872
 
@@ -875,7 +875,7 @@ def align_version(
875
875
  # update version to major.minor.patch
876
876
  if (
877
877
  K_VERSION not in data
878
- or data[K_VERSION] == None
878
+ or data[K_VERSION] is None
879
879
  or data[K_VERSION] != version
880
880
  ):
881
881
  data[K_VERSION] = version
@@ -891,7 +891,7 @@ def align_version(
891
891
  # update compatibleToVersion to previous major.minor
892
892
  if (
893
893
  K_COMPAT not in data
894
- or data[K_COMPAT] == None
894
+ or data[K_COMPAT] is None
895
895
  or data[K_COMPAT] != compat_version
896
896
  ):
897
897
  data[K_COMPAT] = compat_version
@@ -1 +1,29 @@
1
- from .config import *
1
+ """Config module for MCLI."""
2
+
3
+ from .config import (
4
+ DEV_SECRETS_ROOT,
5
+ ENDPOINT,
6
+ PACKAGES_TO_SYNC,
7
+ PATH_TO_PACKAGE_REPO,
8
+ PRIVATE_KEY_PATH,
9
+ USER_CONFIG_ROOT,
10
+ USER_INFO_FILE,
11
+ get_config_directory,
12
+ get_config_file_name,
13
+ get_config_for_file,
14
+ get_mcli_rc,
15
+ )
16
+
17
+ __all__ = [
18
+ "DEV_SECRETS_ROOT",
19
+ "ENDPOINT",
20
+ "PACKAGES_TO_SYNC",
21
+ "PATH_TO_PACKAGE_REPO",
22
+ "PRIVATE_KEY_PATH",
23
+ "USER_CONFIG_ROOT",
24
+ "USER_INFO_FILE",
25
+ "get_config_directory",
26
+ "get_config_file_name",
27
+ "get_config_for_file",
28
+ "get_mcli_rc",
29
+ ]
mcli/lib/config/config.py CHANGED
@@ -2,7 +2,6 @@ from pathlib import Path
2
2
 
3
3
  from mcli.lib.fs import get_user_home
4
4
  from mcli.lib.logger.logger import get_logger
5
- from mcli.lib.toml import read_from_toml
6
5
 
7
6
  logger = get_logger(__name__)
8
7
  logger.info("")
@@ -423,7 +423,7 @@ class CustomCommandManager:
423
423
  ctx.exit(1)
424
424
  finally:
425
425
  # Clean up temporary file
426
- try:
426
+ try: # noqa: SIM105
427
427
  Path(temp_file_path).unlink(missing_ok=True)
428
428
  except Exception:
429
429
  pass
@@ -14,7 +14,7 @@ logger = get_logger(__name__)
14
14
 
15
15
  @dataclass
16
16
  class DiscoveredCommand:
17
- """Represents a discovered Click command"""
17
+ """Represents a discovered Click command."""
18
18
 
19
19
  name: str
20
20
  full_name: str # e.g., "workflow.file.oxps_to_pdf"
@@ -27,14 +27,14 @@ class DiscoveredCommand:
27
27
 
28
28
 
29
29
  class ClickCommandDiscovery:
30
- """Discovers all Click commands in the MCLI application"""
30
+ """Discovers all Click commands in the MCLI application."""
31
31
 
32
32
  def __init__(self, base_path: Optional[Path] = None):
33
33
  self.base_path = base_path or Path(__file__).parent.parent.parent
34
34
  self.discovered_commands: Dict[str, DiscoveredCommand] = {}
35
35
 
36
36
  def discover_all_commands(self) -> List[DiscoveredCommand]:
37
- """Discover all Click commands in the application"""
37
+ """Discover all Click commands in the application."""
38
38
  self.discovered_commands.clear()
39
39
 
40
40
  # Get the included directories from config
@@ -63,7 +63,7 @@ class ClickCommandDiscovery:
63
63
  return list(self.discovered_commands.values())
64
64
 
65
65
  def _discover_in_directory(self, directory: str):
66
- """Discover commands in a specific directory"""
66
+ """Discover commands in a specific directory."""
67
67
  if "/" in directory:
68
68
  # Handle nested paths like "workflow/daemon"
69
69
  parts = directory.split("/")
@@ -90,7 +90,7 @@ class ClickCommandDiscovery:
90
90
  logger.debug(f"Error discovering commands in {py_file}: {e}")
91
91
 
92
92
  def _discover_in_file(self, py_file: Path, base_directory: str):
93
- """Discover commands in a specific Python file"""
93
+ """Discover commands in a specific Python file."""
94
94
  # Convert file path to module name
95
95
  relative_path = py_file.relative_to(self.base_path.parent)
96
96
  module_name = str(relative_path).replace("/", ".").replace(".py", "")
@@ -101,13 +101,13 @@ class ClickCommandDiscovery:
101
101
 
102
102
  try:
103
103
  # Import the module
104
- if module_name not in sys.modules:
104
+ if module_name not in sys.modules: # noqa: SIM401
105
105
  module = importlib.import_module(module_name)
106
106
  else:
107
107
  module = sys.modules[module_name]
108
108
 
109
109
  # Find Click objects
110
- for name, obj in inspect.getmembers(module):
110
+ for _name, obj in inspect.getmembers(module):
111
111
  if isinstance(obj, click.Group):
112
112
  self._register_group(obj, module_name, base_directory)
113
113
  elif isinstance(obj, click.Command):
@@ -117,7 +117,7 @@ class ClickCommandDiscovery:
117
117
  logger.debug(f"Could not import or inspect module {module_name}: {e}")
118
118
 
119
119
  def _register_group(self, group: click.Group, module_name: str, base_directory: str):
120
- """Register a Click group and its commands"""
120
+ """Register a Click group and its commands."""
121
121
  group_full_name = f"{base_directory}.{group.name}" if group.name else base_directory
122
122
 
123
123
  # Register the group itself
@@ -156,7 +156,7 @@ class ClickCommandDiscovery:
156
156
  self._register_group_recursive(cmd, cmd_full_name, module_name)
157
157
 
158
158
  def _register_command(self, command: click.Command, module_name: str, base_directory: str):
159
- """Register a standalone Click command"""
159
+ """Register a standalone Click command."""
160
160
  cmd_full_name = f"{base_directory}.{command.name}" if command.name else base_directory
161
161
 
162
162
  cmd = DiscoveredCommand(
@@ -172,7 +172,7 @@ class ClickCommandDiscovery:
172
172
  self.discovered_commands[cmd_full_name] = cmd
173
173
 
174
174
  def _register_group_recursive(self, group: click.Group, parent_name: str, module_name: str):
175
- """Recursively register nested group commands"""
175
+ """Recursively register nested group commands."""
176
176
  for cmd_name, cmd in group.commands.items():
177
177
  cmd_full_name = f"{parent_name}.{cmd_name}"
178
178
 
@@ -192,7 +192,7 @@ class ClickCommandDiscovery:
192
192
  self._register_group_recursive(cmd, cmd_full_name, module_name)
193
193
 
194
194
  def get_commands(self, include_groups: bool = True) -> List[Dict[str, Any]]:
195
- """Get all discovered commands as dictionaries"""
195
+ """Get all discovered commands as dictionaries."""
196
196
  commands = []
197
197
 
198
198
  for cmd in self.discovered_commands.values():
@@ -224,7 +224,7 @@ class ClickCommandDiscovery:
224
224
  return sorted(commands, key=lambda x: x["full_name"])
225
225
 
226
226
  def search_commands(self, query: str) -> List[Dict[str, Any]]:
227
- """Search commands by name, description, or module"""
227
+ """Search commands by name, description, or module."""
228
228
  query = query.lower()
229
229
  all_commands = self.get_commands()
230
230
 
@@ -241,7 +241,7 @@ class ClickCommandDiscovery:
241
241
  return matching_commands
242
242
 
243
243
  def get_command_by_name(self, name: str) -> Optional[DiscoveredCommand]:
244
- """Get a command by its name or full name"""
244
+ """Get a command by its name or full name."""
245
245
  # First try exact match by full name
246
246
  if name in self.discovered_commands:
247
247
  return self.discovered_commands[name]
@@ -259,7 +259,7 @@ _discovery_instance = None
259
259
 
260
260
 
261
261
  def get_command_discovery() -> ClickCommandDiscovery:
262
- """Get a cached command discovery instance"""
262
+ """Get a cached command discovery instance."""
263
263
  global _discovery_instance
264
264
  if _discovery_instance is None:
265
265
  _discovery_instance = ClickCommandDiscovery()
@@ -268,7 +268,7 @@ def get_command_discovery() -> ClickCommandDiscovery:
268
268
 
269
269
 
270
270
  def refresh_command_discovery():
271
- """Refresh the command discovery cache"""
271
+ """Refresh the command discovery cache."""
272
272
  global _discovery_instance
273
273
  _discovery_instance = None
274
274
  return get_command_discovery()