mcli-framework 7.12.2__py3-none-any.whl → 7.12.4__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.
- mcli/app/__init__.py +0 -2
- mcli/app/commands_cmd.py +30 -26
- mcli/app/completion_helpers.py +5 -5
- mcli/app/init_cmd.py +10 -10
- mcli/app/lock_cmd.py +29 -24
- mcli/app/main.py +2 -8
- mcli/app/model/model.py +5 -10
- mcli/app/store_cmd.py +8 -8
- mcli/app/video/__init__.py +0 -2
- mcli/app/video/video.py +1 -14
- mcli/chat/chat.py +90 -108
- mcli/chat/command_rag.py +0 -4
- mcli/chat/enhanced_chat.py +32 -41
- mcli/chat/system_controller.py +37 -37
- mcli/chat/system_integration.py +4 -5
- mcli/cli.py +2 -3
- mcli/lib/api/api.py +4 -9
- mcli/lib/api/daemon_client.py +19 -20
- mcli/lib/api/daemon_client_local.py +1 -3
- mcli/lib/api/daemon_decorator.py +6 -6
- mcli/lib/api/mcli_decorators.py +4 -8
- mcli/lib/auth/__init__.py +0 -1
- mcli/lib/auth/auth.py +4 -5
- mcli/lib/auth/mcli_manager.py +7 -12
- mcli/lib/auth/token_util.py +5 -5
- mcli/lib/config/__init__.py +29 -1
- mcli/lib/config/config.py +0 -1
- mcli/lib/custom_commands.py +1 -1
- mcli/lib/discovery/command_discovery.py +15 -15
- mcli/lib/erd/erd.py +7 -7
- mcli/lib/files/files.py +1 -1
- mcli/lib/fs/__init__.py +31 -1
- mcli/lib/fs/fs.py +12 -13
- mcli/lib/lib.py +0 -1
- mcli/lib/logger/logger.py +7 -10
- mcli/lib/performance/optimizer.py +25 -27
- mcli/lib/performance/rust_bridge.py +22 -27
- mcli/lib/performance/uvloop_config.py +0 -1
- mcli/lib/pickles/__init__.py +0 -1
- mcli/lib/pickles/pickles.py +0 -2
- mcli/lib/secrets/commands.py +0 -2
- mcli/lib/secrets/manager.py +0 -1
- mcli/lib/secrets/repl.py +2 -3
- mcli/lib/secrets/store.py +1 -2
- mcli/lib/services/data_pipeline.py +34 -34
- mcli/lib/services/lsh_client.py +38 -40
- mcli/lib/shell/shell.py +2 -2
- mcli/lib/toml/__init__.py +0 -1
- mcli/lib/ui/styling.py +0 -1
- mcli/lib/ui/visual_effects.py +33 -41
- mcli/lib/watcher/watcher.py +0 -1
- mcli/ml/__init__.py +1 -1
- mcli/ml/api/__init__.py +1 -1
- mcli/ml/api/app.py +8 -9
- mcli/ml/api/middleware.py +10 -10
- mcli/ml/api/routers/__init__.py +1 -1
- mcli/ml/api/routers/admin_router.py +3 -3
- mcli/ml/api/routers/auth_router.py +17 -18
- mcli/ml/api/routers/backtest_router.py +2 -2
- mcli/ml/api/routers/data_router.py +2 -2
- mcli/ml/api/routers/model_router.py +14 -15
- mcli/ml/api/routers/monitoring_router.py +2 -2
- mcli/ml/api/routers/portfolio_router.py +2 -2
- mcli/ml/api/routers/prediction_router.py +10 -9
- mcli/ml/api/routers/trade_router.py +2 -2
- mcli/ml/api/routers/websocket_router.py +6 -7
- mcli/ml/api/schemas.py +2 -2
- mcli/ml/auth/__init__.py +1 -1
- mcli/ml/auth/auth_manager.py +22 -23
- mcli/ml/auth/models.py +17 -17
- mcli/ml/auth/permissions.py +17 -17
- mcli/ml/backtesting/__init__.py +1 -1
- mcli/ml/backtesting/backtest_engine.py +31 -35
- mcli/ml/backtesting/performance_metrics.py +12 -14
- mcli/ml/backtesting/run.py +1 -2
- mcli/ml/cache.py +35 -36
- mcli/ml/cli/__init__.py +1 -1
- mcli/ml/cli/main.py +21 -24
- mcli/ml/config/__init__.py +1 -1
- mcli/ml/config/settings.py +28 -29
- mcli/ml/configs/__init__.py +1 -1
- mcli/ml/configs/dvc_config.py +14 -15
- mcli/ml/configs/mlflow_config.py +12 -13
- mcli/ml/configs/mlops_manager.py +19 -21
- mcli/ml/dashboard/__init__.py +4 -4
- mcli/ml/dashboard/app.py +20 -30
- mcli/ml/dashboard/app_supabase.py +16 -19
- mcli/ml/dashboard/app_training.py +11 -14
- mcli/ml/dashboard/cli.py +2 -2
- mcli/ml/dashboard/common.py +2 -3
- mcli/ml/dashboard/components/__init__.py +1 -1
- mcli/ml/dashboard/components/charts.py +13 -11
- mcli/ml/dashboard/components/metrics.py +7 -7
- mcli/ml/dashboard/components/tables.py +12 -9
- mcli/ml/dashboard/overview.py +2 -2
- mcli/ml/dashboard/pages/__init__.py +1 -1
- mcli/ml/dashboard/pages/cicd.py +15 -18
- mcli/ml/dashboard/pages/debug_dependencies.py +7 -7
- mcli/ml/dashboard/pages/monte_carlo_predictions.py +11 -18
- mcli/ml/dashboard/pages/predictions_enhanced.py +24 -32
- mcli/ml/dashboard/pages/scrapers_and_logs.py +22 -24
- mcli/ml/dashboard/pages/test_portfolio.py +3 -6
- mcli/ml/dashboard/pages/trading.py +16 -18
- mcli/ml/dashboard/pages/workflows.py +20 -30
- mcli/ml/dashboard/utils.py +9 -9
- mcli/ml/dashboard/warning_suppression.py +3 -3
- mcli/ml/data_ingestion/__init__.py +1 -1
- mcli/ml/data_ingestion/api_connectors.py +41 -46
- mcli/ml/data_ingestion/data_pipeline.py +36 -46
- mcli/ml/data_ingestion/stream_processor.py +43 -46
- mcli/ml/database/__init__.py +1 -1
- mcli/ml/database/migrations/env.py +2 -2
- mcli/ml/database/models.py +22 -24
- mcli/ml/database/session.py +14 -14
- mcli/ml/experimentation/__init__.py +1 -1
- mcli/ml/experimentation/ab_testing.py +45 -46
- mcli/ml/features/__init__.py +1 -1
- mcli/ml/features/ensemble_features.py +22 -27
- mcli/ml/features/recommendation_engine.py +30 -30
- mcli/ml/features/stock_features.py +29 -32
- mcli/ml/features/test_feature_engineering.py +10 -11
- mcli/ml/logging.py +4 -4
- mcli/ml/mlops/__init__.py +1 -1
- mcli/ml/mlops/data_versioning.py +29 -30
- mcli/ml/mlops/experiment_tracker.py +24 -24
- mcli/ml/mlops/model_serving.py +31 -34
- mcli/ml/mlops/pipeline_orchestrator.py +27 -35
- mcli/ml/models/__init__.py +5 -6
- mcli/ml/models/base_models.py +23 -23
- mcli/ml/models/ensemble_models.py +31 -31
- mcli/ml/models/recommendation_models.py +18 -19
- mcli/ml/models/test_models.py +14 -16
- mcli/ml/monitoring/__init__.py +1 -1
- mcli/ml/monitoring/drift_detection.py +32 -36
- mcli/ml/monitoring/metrics.py +2 -2
- mcli/ml/optimization/__init__.py +1 -1
- mcli/ml/optimization/optimize.py +1 -2
- mcli/ml/optimization/portfolio_optimizer.py +30 -32
- mcli/ml/predictions/__init__.py +1 -1
- mcli/ml/preprocessing/__init__.py +1 -1
- mcli/ml/preprocessing/data_cleaners.py +22 -23
- mcli/ml/preprocessing/feature_extractors.py +23 -26
- mcli/ml/preprocessing/ml_pipeline.py +23 -23
- mcli/ml/preprocessing/test_preprocessing.py +7 -8
- mcli/ml/scripts/populate_sample_data.py +0 -4
- mcli/ml/serving/serve.py +1 -2
- mcli/ml/tasks.py +17 -17
- mcli/ml/tests/test_integration.py +29 -30
- mcli/ml/tests/test_training_dashboard.py +21 -21
- mcli/ml/trading/__init__.py +1 -1
- mcli/ml/trading/migrations.py +5 -5
- mcli/ml/trading/models.py +21 -23
- mcli/ml/trading/paper_trading.py +16 -13
- mcli/ml/trading/risk_management.py +17 -18
- mcli/ml/trading/trading_service.py +25 -28
- mcli/ml/training/__init__.py +1 -1
- mcli/ml/training/train.py +0 -1
- mcli/public/oi/oi.py +1 -2
- mcli/self/completion_cmd.py +6 -10
- mcli/self/logs_cmd.py +19 -24
- mcli/self/migrate_cmd.py +22 -20
- mcli/self/redis_cmd.py +10 -11
- mcli/self/self_cmd.py +10 -18
- mcli/self/store_cmd.py +10 -12
- mcli/self/visual_cmd.py +9 -14
- mcli/self/zsh_cmd.py +2 -4
- mcli/workflow/daemon/async_command_database.py +23 -24
- mcli/workflow/daemon/async_process_manager.py +27 -29
- mcli/workflow/daemon/client.py +27 -33
- mcli/workflow/daemon/daemon.py +32 -36
- mcli/workflow/daemon/enhanced_daemon.py +24 -33
- mcli/workflow/daemon/process_cli.py +11 -12
- mcli/workflow/daemon/process_manager.py +23 -26
- mcli/workflow/daemon/test_daemon.py +4 -5
- mcli/workflow/dashboard/dashboard_cmd.py +0 -1
- mcli/workflow/doc_convert.py +15 -17
- mcli/workflow/gcloud/__init__.py +0 -1
- mcli/workflow/gcloud/gcloud.py +11 -8
- mcli/workflow/git_commit/ai_service.py +14 -15
- mcli/workflow/lsh_integration.py +9 -11
- mcli/workflow/model_service/client.py +26 -31
- mcli/workflow/model_service/download_and_run_efficient_models.py +10 -14
- mcli/workflow/model_service/lightweight_embedder.py +25 -35
- mcli/workflow/model_service/lightweight_model_server.py +26 -32
- mcli/workflow/model_service/lightweight_test.py +7 -10
- mcli/workflow/model_service/model_service.py +80 -91
- mcli/workflow/model_service/ollama_efficient_runner.py +14 -18
- mcli/workflow/model_service/openai_adapter.py +23 -23
- mcli/workflow/model_service/pdf_processor.py +21 -26
- mcli/workflow/model_service/test_efficient_runner.py +12 -16
- mcli/workflow/model_service/test_example.py +11 -13
- mcli/workflow/model_service/test_integration.py +3 -5
- mcli/workflow/model_service/test_new_features.py +7 -8
- mcli/workflow/notebook/converter.py +1 -1
- mcli/workflow/notebook/notebook_cmd.py +5 -6
- mcli/workflow/notebook/schema.py +0 -1
- mcli/workflow/notebook/validator.py +7 -3
- mcli/workflow/openai/openai.py +1 -2
- mcli/workflow/registry/registry.py +4 -1
- mcli/workflow/repo/repo.py +6 -7
- mcli/workflow/scheduler/cron_parser.py +16 -19
- mcli/workflow/scheduler/job.py +10 -10
- mcli/workflow/scheduler/monitor.py +15 -15
- mcli/workflow/scheduler/persistence.py +17 -18
- mcli/workflow/scheduler/scheduler.py +37 -38
- mcli/workflow/secrets/__init__.py +1 -1
- mcli/workflow/sync/test_cmd.py +0 -1
- mcli/workflow/wakatime/__init__.py +5 -9
- mcli/workflow/wakatime/wakatime.py +1 -2
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/METADATA +1 -1
- mcli_framework-7.12.4.dist-info/RECORD +279 -0
- mcli_framework-7.12.2.dist-info/RECORD +0 -279
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/WHEEL +0 -0
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.12.2.dist-info → mcli_framework-7.12.4.dist-info}/top_level.txt +0 -0
|
@@ -9,12 +9,10 @@ This script demonstrates how to:
|
|
|
9
9
|
4. Test different model types
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
-
import json
|
|
13
12
|
import os
|
|
14
13
|
import subprocess
|
|
15
14
|
import sys
|
|
16
15
|
import time
|
|
17
|
-
from pathlib import Path
|
|
18
16
|
|
|
19
17
|
import requests
|
|
20
18
|
|
|
@@ -25,16 +23,16 @@ from client import ModelServiceClient
|
|
|
25
23
|
|
|
26
24
|
|
|
27
25
|
def check_service_running(url: str = "http://localhost:8000") -> bool:
|
|
28
|
-
"""Check if the model service is running"""
|
|
26
|
+
"""Check if the model service is running."""
|
|
29
27
|
try:
|
|
30
28
|
response = requests.get(f"{url}/health", timeout=5)
|
|
31
29
|
return response.status_code == 200
|
|
32
|
-
except:
|
|
30
|
+
except Exception:
|
|
33
31
|
return False
|
|
34
32
|
|
|
35
33
|
|
|
36
34
|
def start_service():
|
|
37
|
-
"""Start the model service if not running"""
|
|
35
|
+
"""Start the model service if not running."""
|
|
38
36
|
if check_service_running():
|
|
39
37
|
print("✅ Model service is already running")
|
|
40
38
|
return True
|
|
@@ -42,7 +40,7 @@ def start_service():
|
|
|
42
40
|
print("🚀 Starting model service...")
|
|
43
41
|
try:
|
|
44
42
|
# Start the service in the background
|
|
45
|
-
|
|
43
|
+
_process = subprocess.Popen( # noqa: F841
|
|
46
44
|
[sys.executable, "model_service.py", "start"],
|
|
47
45
|
stdout=subprocess.PIPE,
|
|
48
46
|
stderr=subprocess.PIPE,
|
|
@@ -64,7 +62,7 @@ def start_service():
|
|
|
64
62
|
|
|
65
63
|
|
|
66
64
|
def test_text_generation():
|
|
67
|
-
"""Test text generation with a simple model"""
|
|
65
|
+
"""Test text generation with a simple model."""
|
|
68
66
|
print("\n" + "=" * 60)
|
|
69
67
|
print("🧪 Testing Text Generation")
|
|
70
68
|
print("=" * 60)
|
|
@@ -106,7 +104,7 @@ def test_text_generation():
|
|
|
106
104
|
|
|
107
105
|
|
|
108
106
|
def test_text_classification():
|
|
109
|
-
"""Test text classification with a sentiment model"""
|
|
107
|
+
"""Test text classification with a sentiment model."""
|
|
110
108
|
print("\n" + "=" * 60)
|
|
111
109
|
print("🧪 Testing Text Classification")
|
|
112
110
|
print("=" * 60)
|
|
@@ -148,7 +146,7 @@ def test_text_classification():
|
|
|
148
146
|
|
|
149
147
|
|
|
150
148
|
def test_translation():
|
|
151
|
-
"""Test translation with a translation model"""
|
|
149
|
+
"""Test translation with a translation model."""
|
|
152
150
|
print("\n" + "=" * 60)
|
|
153
151
|
print("🧪 Testing Translation")
|
|
154
152
|
print("=" * 60)
|
|
@@ -186,7 +184,7 @@ def test_translation():
|
|
|
186
184
|
|
|
187
185
|
|
|
188
186
|
def test_batch_operations():
|
|
189
|
-
"""Test batch operations and performance"""
|
|
187
|
+
"""Test batch operations and performance."""
|
|
190
188
|
print("\n" + "=" * 60)
|
|
191
189
|
print("🧪 Testing Batch Operations")
|
|
192
190
|
print("=" * 60)
|
|
@@ -231,7 +229,7 @@ def test_batch_operations():
|
|
|
231
229
|
total_time = time.time() - start_time
|
|
232
230
|
|
|
233
231
|
# Display results
|
|
234
|
-
print(
|
|
232
|
+
print("\n📊 Batch Results:")
|
|
235
233
|
print(f"Total time: {total_time:.2f} seconds")
|
|
236
234
|
print(f"Average time per request: {total_time/len(prompts):.2f} seconds")
|
|
237
235
|
|
|
@@ -249,7 +247,7 @@ def test_batch_operations():
|
|
|
249
247
|
|
|
250
248
|
|
|
251
249
|
def test_service_management():
|
|
252
|
-
"""Test service management functions"""
|
|
250
|
+
"""Test service management functions."""
|
|
253
251
|
print("\n" + "=" * 60)
|
|
254
252
|
print("🧪 Testing Service Management")
|
|
255
253
|
print("=" * 60)
|
|
@@ -286,7 +284,7 @@ def test_service_management():
|
|
|
286
284
|
|
|
287
285
|
|
|
288
286
|
def main():
|
|
289
|
-
"""Main test function"""
|
|
287
|
+
"""Main test function."""
|
|
290
288
|
print("🚀 MCLI Model Service Test Suite")
|
|
291
289
|
print("=" * 60)
|
|
292
290
|
|
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
Test script for lightweight model server integration with MCLI model service
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
import json
|
|
7
6
|
import sys
|
|
8
|
-
import time
|
|
9
7
|
from pathlib import Path
|
|
10
8
|
|
|
11
9
|
import requests
|
|
@@ -17,7 +15,7 @@ from mcli.workflow.model_service.model_service import LIGHTWEIGHT_MODELS, ModelS
|
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
def test_lightweight_integration():
|
|
20
|
-
"""Test the lightweight server integration"""
|
|
18
|
+
"""Test the lightweight server integration."""
|
|
21
19
|
print("🧪 Testing Lightweight Model Server Integration")
|
|
22
20
|
print("=" * 60)
|
|
23
21
|
|
|
@@ -86,7 +84,7 @@ def test_lightweight_integration():
|
|
|
86
84
|
|
|
87
85
|
|
|
88
86
|
def test_cli_commands():
|
|
89
|
-
"""Test CLI commands"""
|
|
87
|
+
"""Test CLI commands."""
|
|
90
88
|
print("\n🧪 Testing CLI Commands")
|
|
91
89
|
print("=" * 40)
|
|
92
90
|
|
|
@@ -100,7 +98,7 @@ def test_cli_commands():
|
|
|
100
98
|
|
|
101
99
|
|
|
102
100
|
def main():
|
|
103
|
-
"""Main test function"""
|
|
101
|
+
"""Main test function."""
|
|
104
102
|
print("🚀 MCLI Lightweight Model Server Integration Test")
|
|
105
103
|
print("=" * 70)
|
|
106
104
|
|
|
@@ -5,18 +5,17 @@ Test script for the new model service features:
|
|
|
5
5
|
2. Add model from URL functionality
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import os
|
|
9
8
|
import sys
|
|
10
9
|
from pathlib import Path
|
|
11
10
|
|
|
12
11
|
# Add the parent directory to the path so we can import the model service
|
|
13
12
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
|
14
13
|
|
|
15
|
-
from mcli.workflow.model_service.model_service import
|
|
14
|
+
from mcli.workflow.model_service.model_service import ModelService
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
def test_list_models():
|
|
19
|
-
"""Test the list models functionality"""
|
|
18
|
+
"""Test the list models functionality."""
|
|
20
19
|
print("🧪 Testing list models functionality...")
|
|
21
20
|
|
|
22
21
|
try:
|
|
@@ -35,7 +34,7 @@ def test_list_models():
|
|
|
35
34
|
|
|
36
35
|
# Test summary
|
|
37
36
|
summary = service.model_manager.get_models_summary()
|
|
38
|
-
print(
|
|
37
|
+
print("\n📊 Summary:")
|
|
39
38
|
print(f" Total models: {summary['total_models']}")
|
|
40
39
|
print(f" Loaded models: {summary['loaded_models']}")
|
|
41
40
|
print(f" Total memory: {summary['total_memory_mb']:.1f} MB")
|
|
@@ -50,7 +49,7 @@ def test_list_models():
|
|
|
50
49
|
|
|
51
50
|
|
|
52
51
|
def test_add_model_from_url():
|
|
53
|
-
"""Test the add model from URL functionality"""
|
|
52
|
+
"""Test the add model from URL functionality."""
|
|
54
53
|
print("\n🧪 Testing add model from URL functionality...")
|
|
55
54
|
|
|
56
55
|
try:
|
|
@@ -60,7 +59,7 @@ def test_add_model_from_url():
|
|
|
60
59
|
test_model_url = (
|
|
61
60
|
"https://huggingface.co/microsoft/DialoGPT-small/resolve/main/pytorch_model.bin"
|
|
62
61
|
)
|
|
63
|
-
|
|
62
|
+
_test_tokenizer_url = ( # noqa: F841
|
|
64
63
|
"https://huggingface.co/microsoft/DialoGPT-small/resolve/main/tokenizer.json"
|
|
65
64
|
)
|
|
66
65
|
|
|
@@ -92,7 +91,7 @@ def test_add_model_from_url():
|
|
|
92
91
|
|
|
93
92
|
|
|
94
93
|
def test_api_endpoints():
|
|
95
|
-
"""Test that the new API endpoints are properly defined"""
|
|
94
|
+
"""Test that the new API endpoints are properly defined."""
|
|
96
95
|
print("\n🧪 Testing API endpoints...")
|
|
97
96
|
|
|
98
97
|
try:
|
|
@@ -120,7 +119,7 @@ def test_api_endpoints():
|
|
|
120
119
|
|
|
121
120
|
|
|
122
121
|
def main():
|
|
123
|
-
"""Run all tests"""
|
|
122
|
+
"""Run all tests."""
|
|
124
123
|
print("🚀 Testing new model service features...")
|
|
125
124
|
print("=" * 50)
|
|
126
125
|
|
|
@@ -27,8 +27,7 @@ logger = get_logger()
|
|
|
27
27
|
|
|
28
28
|
@click.group(name="notebook")
|
|
29
29
|
def notebook():
|
|
30
|
-
"""Workflow notebook management commands"""
|
|
31
|
-
pass
|
|
30
|
+
"""Workflow notebook management commands."""
|
|
32
31
|
|
|
33
32
|
|
|
34
33
|
@notebook.command(name="convert")
|
|
@@ -153,7 +152,7 @@ def migrate(directory: Optional[str], backup: bool, in_place: bool, dry_run: boo
|
|
|
153
152
|
try:
|
|
154
153
|
results = WorkflowConverter.migrate_directory(target_dir, backup=backup, in_place=in_place)
|
|
155
154
|
|
|
156
|
-
success(
|
|
155
|
+
success("\nMigration complete:")
|
|
157
156
|
info(f" Total files: {results['total']}")
|
|
158
157
|
success(f" Converted: {results['converted']}")
|
|
159
158
|
warning(f" Skipped: {results['skipped']}")
|
|
@@ -203,7 +202,7 @@ def validate(notebook_file: str, schema: bool, syntax: bool, validate_all: bool)
|
|
|
203
202
|
# Run all validations
|
|
204
203
|
mcli workflow notebook validate notebook.json --all
|
|
205
204
|
"""
|
|
206
|
-
if validate_all:
|
|
205
|
+
if validate_all: # noqa: SIM114
|
|
207
206
|
schema = syntax = True
|
|
208
207
|
elif not (schema or syntax):
|
|
209
208
|
# Default to all if no specific validation requested
|
|
@@ -300,7 +299,7 @@ def notebook_info(notebook_file: str, output_json: bool):
|
|
|
300
299
|
info(f"Group: {notebook.metadata.mcli.group}")
|
|
301
300
|
info(f"Version: {notebook.metadata.mcli.version}")
|
|
302
301
|
info(f"Language: {notebook.metadata.mcli.language.value}")
|
|
303
|
-
info(
|
|
302
|
+
info("\nCells:")
|
|
304
303
|
info(f" Total: {len(notebook.cells)}")
|
|
305
304
|
info(f" Code: {len(notebook.code_cells)}")
|
|
306
305
|
info(f" Markdown: {len(notebook.markdown_cells)}")
|
|
@@ -368,7 +367,7 @@ def create(name: str, description: str, group: Optional[str], language: str, out
|
|
|
368
367
|
# Add welcome markdown cell
|
|
369
368
|
notebook.add_markdown_cell(
|
|
370
369
|
f"# {name}\n\n{description}\n\n"
|
|
371
|
-
|
|
370
|
+
"This is a workflow notebook. Add code cells below to define your workflow."
|
|
372
371
|
)
|
|
373
372
|
|
|
374
373
|
# Add example code cell
|
mcli/workflow/notebook/schema.py
CHANGED
|
@@ -12,7 +12,7 @@ import ast
|
|
|
12
12
|
import subprocess
|
|
13
13
|
import tempfile
|
|
14
14
|
from pathlib import Path
|
|
15
|
-
from typing import
|
|
15
|
+
from typing import Dict, List
|
|
16
16
|
|
|
17
17
|
from mcli.lib.logger.logger import get_logger
|
|
18
18
|
|
|
@@ -105,7 +105,11 @@ class NotebookValidator:
|
|
|
105
105
|
if not self._validate_python_syntax(code, i):
|
|
106
106
|
all_valid = False
|
|
107
107
|
|
|
108
|
-
elif language in (
|
|
108
|
+
elif language in (
|
|
109
|
+
CellLanguage.SHELL,
|
|
110
|
+
CellLanguage.BASH,
|
|
111
|
+
CellLanguage.ZSH,
|
|
112
|
+
): # noqa: SIM102
|
|
109
113
|
if not self._validate_shell_syntax(code, i):
|
|
110
114
|
all_valid = False
|
|
111
115
|
|
|
@@ -281,7 +285,7 @@ class CodeLinter:
|
|
|
281
285
|
try:
|
|
282
286
|
# Try to use shellcheck
|
|
283
287
|
result = subprocess.run(
|
|
284
|
-
["shellcheck", "-
|
|
288
|
+
["shellcheck", "-", "json", temp_path],
|
|
285
289
|
capture_output=True,
|
|
286
290
|
text=True,
|
|
287
291
|
timeout=10,
|
mcli/workflow/openai/openai.py
CHANGED
|
@@ -43,7 +43,7 @@ class OpenAI:
|
|
|
43
43
|
|
|
44
44
|
See https://platform.openai.com/docs/guides/moderation/quickstart for details.
|
|
45
45
|
"""
|
|
46
|
-
|
|
46
|
+
_allowed_categories = {"violence"} # Can be triggered by some AI safety terms # noqa: F841
|
|
47
47
|
|
|
48
48
|
response = None
|
|
49
49
|
try:
|
|
@@ -79,7 +79,6 @@ class OpenAI:
|
|
|
79
79
|
@click.group(name="openai")
|
|
80
80
|
def openai():
|
|
81
81
|
"""OpenAI CLI command group."""
|
|
82
|
-
pass
|
|
83
82
|
|
|
84
83
|
|
|
85
84
|
@openai.command(name="is_text_risky")
|
|
@@ -7,6 +7,10 @@ import requests
|
|
|
7
7
|
warnings.filterwarnings("ignore", message="Using slow pure-python SequenceMatcher")
|
|
8
8
|
from fuzzywuzzy import process
|
|
9
9
|
|
|
10
|
+
from mcli.lib.logger.logger import get_logger
|
|
11
|
+
|
|
12
|
+
logger = get_logger(__name__)
|
|
13
|
+
|
|
10
14
|
"""_summary_
|
|
11
15
|
ssh -o GatewayPorts=yes -o ServerAliveInterval=60 -o ProxyCommand="ssh -W %h:%p myuser@my-proxy-server" -L80::80 -L443::443 myuser@localhost
|
|
12
16
|
Returns:
|
|
@@ -56,7 +60,6 @@ class DockerClient:
|
|
|
56
60
|
logger.info(f"{repo}: {matching_tuples}")
|
|
57
61
|
except Exception as e:
|
|
58
62
|
logger.info(e)
|
|
59
|
-
pass
|
|
60
63
|
return response
|
|
61
64
|
|
|
62
65
|
def count_images(self, repository):
|
mcli/workflow/repo/repo.py
CHANGED
|
@@ -14,14 +14,14 @@ logger = get_logger(__name__)
|
|
|
14
14
|
|
|
15
15
|
@click.group(name="repo")
|
|
16
16
|
def repo():
|
|
17
|
-
"""repo utility - use this to interact with git and relevant utilities"""
|
|
17
|
+
"""repo utility - use this to interact with git and relevant utilities."""
|
|
18
18
|
click.echo("repo")
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
@repo.command()
|
|
22
22
|
@click.argument("path")
|
|
23
23
|
def analyze(path: str):
|
|
24
|
-
"""Provides a source lines of code analysis for a given pkg path"""
|
|
24
|
+
"""Provides a source lines of code analysis for a given pkg path."""
|
|
25
25
|
_analyze(path)
|
|
26
26
|
|
|
27
27
|
|
|
@@ -68,7 +68,6 @@ def _analyze(path: str):
|
|
|
68
68
|
max_length = len(cell.value)
|
|
69
69
|
except Exception as e:
|
|
70
70
|
logger.info(e)
|
|
71
|
-
pass
|
|
72
71
|
adjusted_width = max_length + 2
|
|
73
72
|
worksheet.column_dimensions[column].width = adjusted_width
|
|
74
73
|
for cell in col:
|
|
@@ -147,20 +146,20 @@ def _analyze(path: str):
|
|
|
147
146
|
|
|
148
147
|
@repo.command(name="wt")
|
|
149
148
|
def worktree():
|
|
150
|
-
"""Create and manage worktrees"""
|
|
149
|
+
"""Create and manage worktrees."""
|
|
151
150
|
scripts_path = get_shell_script_path("repo", __file__)
|
|
152
151
|
shell_exec(scripts_path, "wt")
|
|
153
152
|
|
|
154
153
|
|
|
155
154
|
@repo.command(name="commit")
|
|
156
155
|
def commit():
|
|
157
|
-
"""Edit commits to a repository"""
|
|
156
|
+
"""Edit commits to a repository."""
|
|
158
157
|
click.echo("commit")
|
|
159
158
|
|
|
160
159
|
|
|
161
160
|
@repo.command(name="revert")
|
|
162
161
|
def revert():
|
|
163
|
-
"""Create and manage worktrees"""
|
|
162
|
+
"""Create and manage worktrees."""
|
|
164
163
|
scripts_path = get_shell_script_path("repo", __file__)
|
|
165
164
|
shell_exec(scripts_path, "revert")
|
|
166
165
|
|
|
@@ -169,7 +168,7 @@ def revert():
|
|
|
169
168
|
@click.argument("branch-a")
|
|
170
169
|
@click.argument("branch-b")
|
|
171
170
|
def loe(branch_a: str, branch_b: str):
|
|
172
|
-
"""Create and manage worktrees"""
|
|
171
|
+
"""Create and manage worktrees."""
|
|
173
172
|
scripts_path = get_shell_script_path("repo", __file__)
|
|
174
173
|
result = shell_exec(scripts_path, "migration_loe", branch_a, branch_b)
|
|
175
174
|
# Assume result['result'] contains the output from the shell script
|
|
@@ -7,7 +7,6 @@ Supports standard cron expressions with some extensions:
|
|
|
7
7
|
- Special: @reboot (run at scheduler start)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
import re
|
|
11
10
|
from datetime import datetime, timedelta
|
|
12
11
|
from typing import List, Optional, Set
|
|
13
12
|
|
|
@@ -17,13 +16,11 @@ logger = get_logger(__name__)
|
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
class CronParseError(Exception):
|
|
20
|
-
"""Exception raised when cron expression cannot be parsed"""
|
|
21
|
-
|
|
22
|
-
pass
|
|
19
|
+
"""Exception raised when cron expression cannot be parsed."""
|
|
23
20
|
|
|
24
21
|
|
|
25
22
|
class CronExpression:
|
|
26
|
-
"""Parser and calculator for cron expressions"""
|
|
23
|
+
"""Parser and calculator for cron expressions."""
|
|
27
24
|
|
|
28
25
|
# Predefined cron shortcuts
|
|
29
26
|
SHORTCUTS = {
|
|
@@ -47,7 +44,7 @@ class CronExpression:
|
|
|
47
44
|
self._validate_fields()
|
|
48
45
|
|
|
49
46
|
def _normalize_expression(self, expression: str) -> str:
|
|
50
|
-
"""Convert shortcuts to standard cron format"""
|
|
47
|
+
"""Convert shortcuts to standard cron format."""
|
|
51
48
|
expression = expression.strip().lower()
|
|
52
49
|
|
|
53
50
|
if expression in self.SHORTCUTS:
|
|
@@ -56,7 +53,7 @@ class CronExpression:
|
|
|
56
53
|
return expression
|
|
57
54
|
|
|
58
55
|
def _parse_expression(self) -> List[Set[int]]:
|
|
59
|
-
"""Parse cron expression into field sets"""
|
|
56
|
+
"""Parse cron expression into field sets."""
|
|
60
57
|
if self.is_reboot:
|
|
61
58
|
return []
|
|
62
59
|
|
|
@@ -73,14 +70,14 @@ class CronExpression:
|
|
|
73
70
|
(0, 6), # weekday (0=Sunday)
|
|
74
71
|
]
|
|
75
72
|
|
|
76
|
-
for
|
|
73
|
+
for _i, (part, (min_val, max_val)) in enumerate(zip(parts, ranges)):
|
|
77
74
|
field_values = self._parse_field(part, min_val, max_val)
|
|
78
75
|
fields.append(field_values)
|
|
79
76
|
|
|
80
77
|
return fields
|
|
81
78
|
|
|
82
79
|
def _parse_field(self, field: str, min_val: int, max_val: int) -> Set[int]:
|
|
83
|
-
"""Parse a single cron field"""
|
|
80
|
+
"""Parse a single cron field."""
|
|
84
81
|
if field == "*":
|
|
85
82
|
return set(range(min_val, max_val + 1))
|
|
86
83
|
|
|
@@ -121,12 +118,12 @@ class CronExpression:
|
|
|
121
118
|
return values
|
|
122
119
|
|
|
123
120
|
def _validate_fields(self):
|
|
124
|
-
"""Validate parsed cron fields"""
|
|
121
|
+
"""Validate parsed cron fields."""
|
|
125
122
|
if len(self.fields) != 5:
|
|
126
123
|
raise CronParseError("Invalid number of parsed fields")
|
|
127
124
|
|
|
128
125
|
def get_next_run_time(self, from_time: Optional[datetime] = None) -> Optional[datetime]:
|
|
129
|
-
"""Calculate the next time this cron expression should run"""
|
|
126
|
+
"""Calculate the next time this cron expression should run."""
|
|
130
127
|
if self.is_reboot:
|
|
131
128
|
return None # @reboot jobs run only at scheduler start
|
|
132
129
|
|
|
@@ -151,7 +148,7 @@ class CronExpression:
|
|
|
151
148
|
return None
|
|
152
149
|
|
|
153
150
|
def _matches_time(self, dt: datetime) -> bool:
|
|
154
|
-
"""Check if datetime matches this cron expression"""
|
|
151
|
+
"""Check if datetime matches this cron expression."""
|
|
155
152
|
if self.is_reboot:
|
|
156
153
|
return False
|
|
157
154
|
|
|
@@ -166,11 +163,11 @@ class CronExpression:
|
|
|
166
163
|
)
|
|
167
164
|
|
|
168
165
|
def matches_now(self) -> bool:
|
|
169
|
-
"""Check if cron expression matches current time"""
|
|
166
|
+
"""Check if cron expression matches current time."""
|
|
170
167
|
return self._matches_time(datetime.now())
|
|
171
168
|
|
|
172
169
|
def get_description(self) -> str:
|
|
173
|
-
"""Get human-readable description of cron expression"""
|
|
170
|
+
"""Get human-readable description of cron expression."""
|
|
174
171
|
if self.is_reboot:
|
|
175
172
|
return "Run at scheduler startup"
|
|
176
173
|
|
|
@@ -191,12 +188,12 @@ class CronExpression:
|
|
|
191
188
|
return f"Custom schedule: {self.original_expression}"
|
|
192
189
|
|
|
193
190
|
def is_valid(self) -> bool:
|
|
194
|
-
"""Check if cron expression is valid"""
|
|
191
|
+
"""Check if cron expression is valid."""
|
|
195
192
|
try:
|
|
196
193
|
if self.is_reboot:
|
|
197
194
|
return True
|
|
198
195
|
return len(self.fields) == 5
|
|
199
|
-
except:
|
|
196
|
+
except Exception:
|
|
200
197
|
return False
|
|
201
198
|
|
|
202
199
|
def __str__(self) -> str:
|
|
@@ -207,16 +204,16 @@ class CronExpression:
|
|
|
207
204
|
|
|
208
205
|
|
|
209
206
|
def validate_cron_expression(expression: str) -> bool:
|
|
210
|
-
"""Validate a cron expression without creating a full object"""
|
|
207
|
+
"""Validate a cron expression without creating a full object."""
|
|
211
208
|
try:
|
|
212
209
|
cron = CronExpression(expression)
|
|
213
210
|
return cron.is_valid()
|
|
214
|
-
except:
|
|
211
|
+
except Exception:
|
|
215
212
|
return False
|
|
216
213
|
|
|
217
214
|
|
|
218
215
|
def get_next_run_times(expression: str, count: int = 5) -> List[datetime]:
|
|
219
|
-
"""Get the next N run times for a cron expression"""
|
|
216
|
+
"""Get the next N run times for a cron expression."""
|
|
220
217
|
try:
|
|
221
218
|
cron = CronExpression(expression)
|
|
222
219
|
if cron.is_reboot:
|
mcli/workflow/scheduler/job.py
CHANGED
|
@@ -6,7 +6,7 @@ import json
|
|
|
6
6
|
import uuid
|
|
7
7
|
from datetime import datetime, timedelta
|
|
8
8
|
from enum import Enum
|
|
9
|
-
from typing import Any, Dict,
|
|
9
|
+
from typing import Any, Dict, Optional
|
|
10
10
|
|
|
11
11
|
from mcli.lib.logger.logger import get_logger
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@ logger = get_logger(__name__)
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class JobStatus(Enum):
|
|
17
|
-
"""Job execution status"""
|
|
17
|
+
"""Job execution status."""
|
|
18
18
|
|
|
19
19
|
PENDING = "pending"
|
|
20
20
|
RUNNING = "running"
|
|
@@ -25,7 +25,7 @@ class JobStatus(Enum):
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class JobType(Enum):
|
|
28
|
-
"""Types of jobs that can be scheduled"""
|
|
28
|
+
"""Types of jobs that can be scheduled."""
|
|
29
29
|
|
|
30
30
|
COMMAND = "command" # Execute shell commands
|
|
31
31
|
PYTHON = "python" # Execute Python code
|
|
@@ -36,7 +36,7 @@ class JobType(Enum):
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class ScheduledJob:
|
|
39
|
-
"""Represents a scheduled job with all its metadata"""
|
|
39
|
+
"""Represents a scheduled job with all its metadata."""
|
|
40
40
|
|
|
41
41
|
def __init__(
|
|
42
42
|
self,
|
|
@@ -84,7 +84,7 @@ class ScheduledJob:
|
|
|
84
84
|
self.current_retry = 0
|
|
85
85
|
|
|
86
86
|
def to_dict(self) -> Dict[str, Any]:
|
|
87
|
-
"""Convert job to dictionary for serialization"""
|
|
87
|
+
"""Convert job to dictionary for serialization."""
|
|
88
88
|
return {
|
|
89
89
|
"id": self.id,
|
|
90
90
|
"name": self.name,
|
|
@@ -115,7 +115,7 @@ class ScheduledJob:
|
|
|
115
115
|
|
|
116
116
|
@classmethod
|
|
117
117
|
def from_dict(cls, data: Dict[str, Any]) -> "ScheduledJob":
|
|
118
|
-
"""Create job from dictionary"""
|
|
118
|
+
"""Create job from dictionary."""
|
|
119
119
|
job = cls(
|
|
120
120
|
name=data["name"],
|
|
121
121
|
cron_expression=data["cron_expression"],
|
|
@@ -149,7 +149,7 @@ class ScheduledJob:
|
|
|
149
149
|
return job
|
|
150
150
|
|
|
151
151
|
def update_status(self, status: JobStatus, output: str = "", error: str = ""):
|
|
152
|
-
"""Update job status and related metadata"""
|
|
152
|
+
"""Update job status and related metadata."""
|
|
153
153
|
self.status = status
|
|
154
154
|
self.last_output = output
|
|
155
155
|
self.last_error = error
|
|
@@ -164,15 +164,15 @@ class ScheduledJob:
|
|
|
164
164
|
self.failure_count += 1
|
|
165
165
|
|
|
166
166
|
def should_retry(self) -> bool:
|
|
167
|
-
"""Check if job should be retried after failure"""
|
|
167
|
+
"""Check if job should be retried after failure."""
|
|
168
168
|
return self.status == JobStatus.FAILED and self.current_retry < self.retry_count
|
|
169
169
|
|
|
170
170
|
def get_next_retry_time(self) -> datetime:
|
|
171
|
-
"""Calculate next retry time"""
|
|
171
|
+
"""Calculate next retry time."""
|
|
172
172
|
return datetime.now() + timedelta(seconds=self.retry_delay)
|
|
173
173
|
|
|
174
174
|
def to_json(self) -> str:
|
|
175
|
-
"""Convert job to JSON string"""
|
|
175
|
+
"""Convert job to JSON string."""
|
|
176
176
|
return json.dumps(self.to_dict(), indent=2)
|
|
177
177
|
|
|
178
178
|
def __str__(self) -> str:
|