mcli-framework 7.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.
Potentially problematic release.
This version of mcli-framework might be problematic. Click here for more details.
- mcli/app/chat_cmd.py +42 -0
- mcli/app/commands_cmd.py +226 -0
- mcli/app/completion_cmd.py +216 -0
- mcli/app/completion_helpers.py +288 -0
- mcli/app/cron_test_cmd.py +697 -0
- mcli/app/logs_cmd.py +419 -0
- mcli/app/main.py +492 -0
- mcli/app/model/model.py +1060 -0
- mcli/app/model_cmd.py +227 -0
- mcli/app/redis_cmd.py +269 -0
- mcli/app/video/video.py +1114 -0
- mcli/app/visual_cmd.py +303 -0
- mcli/chat/chat.py +2409 -0
- mcli/chat/command_rag.py +514 -0
- mcli/chat/enhanced_chat.py +652 -0
- mcli/chat/system_controller.py +1010 -0
- mcli/chat/system_integration.py +1016 -0
- mcli/cli.py +25 -0
- mcli/config.toml +20 -0
- mcli/lib/api/api.py +586 -0
- mcli/lib/api/daemon_client.py +203 -0
- mcli/lib/api/daemon_client_local.py +44 -0
- mcli/lib/api/daemon_decorator.py +217 -0
- mcli/lib/api/mcli_decorators.py +1032 -0
- mcli/lib/auth/auth.py +85 -0
- mcli/lib/auth/aws_manager.py +85 -0
- mcli/lib/auth/azure_manager.py +91 -0
- mcli/lib/auth/credential_manager.py +192 -0
- mcli/lib/auth/gcp_manager.py +93 -0
- mcli/lib/auth/key_manager.py +117 -0
- mcli/lib/auth/mcli_manager.py +93 -0
- mcli/lib/auth/token_manager.py +75 -0
- mcli/lib/auth/token_util.py +1011 -0
- mcli/lib/config/config.py +47 -0
- mcli/lib/discovery/__init__.py +1 -0
- mcli/lib/discovery/command_discovery.py +274 -0
- mcli/lib/erd/erd.py +1345 -0
- mcli/lib/erd/generate_graph.py +453 -0
- mcli/lib/files/files.py +76 -0
- mcli/lib/fs/fs.py +109 -0
- mcli/lib/lib.py +29 -0
- mcli/lib/logger/logger.py +611 -0
- mcli/lib/performance/optimizer.py +409 -0
- mcli/lib/performance/rust_bridge.py +502 -0
- mcli/lib/performance/uvloop_config.py +154 -0
- mcli/lib/pickles/pickles.py +50 -0
- mcli/lib/search/cached_vectorizer.py +479 -0
- mcli/lib/services/data_pipeline.py +460 -0
- mcli/lib/services/lsh_client.py +441 -0
- mcli/lib/services/redis_service.py +387 -0
- mcli/lib/shell/shell.py +137 -0
- mcli/lib/toml/toml.py +33 -0
- mcli/lib/ui/styling.py +47 -0
- mcli/lib/ui/visual_effects.py +634 -0
- mcli/lib/watcher/watcher.py +185 -0
- mcli/ml/api/app.py +215 -0
- mcli/ml/api/middleware.py +224 -0
- mcli/ml/api/routers/admin_router.py +12 -0
- mcli/ml/api/routers/auth_router.py +244 -0
- mcli/ml/api/routers/backtest_router.py +12 -0
- mcli/ml/api/routers/data_router.py +12 -0
- mcli/ml/api/routers/model_router.py +302 -0
- mcli/ml/api/routers/monitoring_router.py +12 -0
- mcli/ml/api/routers/portfolio_router.py +12 -0
- mcli/ml/api/routers/prediction_router.py +267 -0
- mcli/ml/api/routers/trade_router.py +12 -0
- mcli/ml/api/routers/websocket_router.py +76 -0
- mcli/ml/api/schemas.py +64 -0
- mcli/ml/auth/auth_manager.py +425 -0
- mcli/ml/auth/models.py +154 -0
- mcli/ml/auth/permissions.py +302 -0
- mcli/ml/backtesting/backtest_engine.py +502 -0
- mcli/ml/backtesting/performance_metrics.py +393 -0
- mcli/ml/cache.py +400 -0
- mcli/ml/cli/main.py +398 -0
- mcli/ml/config/settings.py +394 -0
- mcli/ml/configs/dvc_config.py +230 -0
- mcli/ml/configs/mlflow_config.py +131 -0
- mcli/ml/configs/mlops_manager.py +293 -0
- mcli/ml/dashboard/app.py +532 -0
- mcli/ml/dashboard/app_integrated.py +738 -0
- mcli/ml/dashboard/app_supabase.py +560 -0
- mcli/ml/dashboard/app_training.py +615 -0
- mcli/ml/dashboard/cli.py +51 -0
- mcli/ml/data_ingestion/api_connectors.py +501 -0
- mcli/ml/data_ingestion/data_pipeline.py +567 -0
- mcli/ml/data_ingestion/stream_processor.py +512 -0
- mcli/ml/database/migrations/env.py +94 -0
- mcli/ml/database/models.py +667 -0
- mcli/ml/database/session.py +200 -0
- mcli/ml/experimentation/ab_testing.py +845 -0
- mcli/ml/features/ensemble_features.py +607 -0
- mcli/ml/features/political_features.py +676 -0
- mcli/ml/features/recommendation_engine.py +809 -0
- mcli/ml/features/stock_features.py +573 -0
- mcli/ml/features/test_feature_engineering.py +346 -0
- mcli/ml/logging.py +85 -0
- mcli/ml/mlops/data_versioning.py +518 -0
- mcli/ml/mlops/experiment_tracker.py +377 -0
- mcli/ml/mlops/model_serving.py +481 -0
- mcli/ml/mlops/pipeline_orchestrator.py +614 -0
- mcli/ml/models/base_models.py +324 -0
- mcli/ml/models/ensemble_models.py +675 -0
- mcli/ml/models/recommendation_models.py +474 -0
- mcli/ml/models/test_models.py +487 -0
- mcli/ml/monitoring/drift_detection.py +676 -0
- mcli/ml/monitoring/metrics.py +45 -0
- mcli/ml/optimization/portfolio_optimizer.py +834 -0
- mcli/ml/preprocessing/data_cleaners.py +451 -0
- mcli/ml/preprocessing/feature_extractors.py +491 -0
- mcli/ml/preprocessing/ml_pipeline.py +382 -0
- mcli/ml/preprocessing/politician_trading_preprocessor.py +569 -0
- mcli/ml/preprocessing/test_preprocessing.py +294 -0
- mcli/ml/scripts/populate_sample_data.py +200 -0
- mcli/ml/tasks.py +400 -0
- mcli/ml/tests/test_integration.py +429 -0
- mcli/ml/tests/test_training_dashboard.py +387 -0
- mcli/public/oi/oi.py +15 -0
- mcli/public/public.py +4 -0
- mcli/self/self_cmd.py +1246 -0
- mcli/workflow/daemon/api_daemon.py +800 -0
- mcli/workflow/daemon/async_command_database.py +681 -0
- mcli/workflow/daemon/async_process_manager.py +591 -0
- mcli/workflow/daemon/client.py +530 -0
- mcli/workflow/daemon/commands.py +1196 -0
- mcli/workflow/daemon/daemon.py +905 -0
- mcli/workflow/daemon/daemon_api.py +59 -0
- mcli/workflow/daemon/enhanced_daemon.py +571 -0
- mcli/workflow/daemon/process_cli.py +244 -0
- mcli/workflow/daemon/process_manager.py +439 -0
- mcli/workflow/daemon/test_daemon.py +275 -0
- mcli/workflow/dashboard/dashboard_cmd.py +113 -0
- mcli/workflow/docker/docker.py +0 -0
- mcli/workflow/file/file.py +100 -0
- mcli/workflow/gcloud/config.toml +21 -0
- mcli/workflow/gcloud/gcloud.py +58 -0
- mcli/workflow/git_commit/ai_service.py +328 -0
- mcli/workflow/git_commit/commands.py +430 -0
- mcli/workflow/lsh_integration.py +355 -0
- mcli/workflow/model_service/client.py +594 -0
- mcli/workflow/model_service/download_and_run_efficient_models.py +288 -0
- mcli/workflow/model_service/lightweight_embedder.py +397 -0
- mcli/workflow/model_service/lightweight_model_server.py +714 -0
- mcli/workflow/model_service/lightweight_test.py +241 -0
- mcli/workflow/model_service/model_service.py +1955 -0
- mcli/workflow/model_service/ollama_efficient_runner.py +425 -0
- mcli/workflow/model_service/pdf_processor.py +386 -0
- mcli/workflow/model_service/test_efficient_runner.py +234 -0
- mcli/workflow/model_service/test_example.py +315 -0
- mcli/workflow/model_service/test_integration.py +131 -0
- mcli/workflow/model_service/test_new_features.py +149 -0
- mcli/workflow/openai/openai.py +99 -0
- mcli/workflow/politician_trading/commands.py +1790 -0
- mcli/workflow/politician_trading/config.py +134 -0
- mcli/workflow/politician_trading/connectivity.py +490 -0
- mcli/workflow/politician_trading/data_sources.py +395 -0
- mcli/workflow/politician_trading/database.py +410 -0
- mcli/workflow/politician_trading/demo.py +248 -0
- mcli/workflow/politician_trading/models.py +165 -0
- mcli/workflow/politician_trading/monitoring.py +413 -0
- mcli/workflow/politician_trading/scrapers.py +966 -0
- mcli/workflow/politician_trading/scrapers_california.py +412 -0
- mcli/workflow/politician_trading/scrapers_eu.py +377 -0
- mcli/workflow/politician_trading/scrapers_uk.py +350 -0
- mcli/workflow/politician_trading/scrapers_us_states.py +438 -0
- mcli/workflow/politician_trading/supabase_functions.py +354 -0
- mcli/workflow/politician_trading/workflow.py +852 -0
- mcli/workflow/registry/registry.py +180 -0
- mcli/workflow/repo/repo.py +223 -0
- mcli/workflow/scheduler/commands.py +493 -0
- mcli/workflow/scheduler/cron_parser.py +238 -0
- mcli/workflow/scheduler/job.py +182 -0
- mcli/workflow/scheduler/monitor.py +139 -0
- mcli/workflow/scheduler/persistence.py +324 -0
- mcli/workflow/scheduler/scheduler.py +679 -0
- mcli/workflow/sync/sync_cmd.py +437 -0
- mcli/workflow/sync/test_cmd.py +314 -0
- mcli/workflow/videos/videos.py +242 -0
- mcli/workflow/wakatime/wakatime.py +11 -0
- mcli/workflow/workflow.py +37 -0
- mcli_framework-7.0.0.dist-info/METADATA +479 -0
- mcli_framework-7.0.0.dist-info/RECORD +186 -0
- mcli_framework-7.0.0.dist-info/WHEEL +5 -0
- mcli_framework-7.0.0.dist-info/entry_points.txt +7 -0
- mcli_framework-7.0.0.dist-info/licenses/LICENSE +21 -0
- mcli_framework-7.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
import requests
|
|
5
|
+
|
|
6
|
+
# Suppress the warning about python-Levenshtein
|
|
7
|
+
warnings.filterwarnings("ignore", message="Using slow pure-python SequenceMatcher")
|
|
8
|
+
from fuzzywuzzy import process
|
|
9
|
+
|
|
10
|
+
"""_summary_
|
|
11
|
+
ssh -o GatewayPorts=yes -o ServerAliveInterval=60 -o ProxyCommand="ssh -W %h:%p myuser@my-proxy-server" -L80::80 -L443::443 myuser@localhost
|
|
12
|
+
Returns:
|
|
13
|
+
_type_: _description_
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class DockerClient:
|
|
18
|
+
def __init__(self, registry_url):
|
|
19
|
+
self.registry_url = registry_url
|
|
20
|
+
|
|
21
|
+
def _make_request(self, endpoint):
|
|
22
|
+
url = f"{self.registry_url}/{endpoint}"
|
|
23
|
+
try:
|
|
24
|
+
response = requests.get(url)
|
|
25
|
+
response.raise_for_status()
|
|
26
|
+
return response.json()
|
|
27
|
+
except requests.exceptions.RequestException as e:
|
|
28
|
+
logger.info(f"Error fetching data from {url}: {e}")
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
def get_catalog(self):
|
|
32
|
+
return self._make_request("v2/_catalog")
|
|
33
|
+
|
|
34
|
+
def get_tags(self, repository):
|
|
35
|
+
return self._make_request(f"v2/{repository}/tags/list")
|
|
36
|
+
|
|
37
|
+
def search_repository(self, repository):
|
|
38
|
+
catalog = self.get_catalog()
|
|
39
|
+
if catalog:
|
|
40
|
+
return [repo for repo in catalog.get("repositories", []) if repository in repo]
|
|
41
|
+
return []
|
|
42
|
+
|
|
43
|
+
def search_all_repositories(self, token: str):
|
|
44
|
+
logger.info("search_all_repositories")
|
|
45
|
+
catalog = self.get_catalog()
|
|
46
|
+
response = []
|
|
47
|
+
for repo in catalog.get("repositories", []):
|
|
48
|
+
try:
|
|
49
|
+
tags = self.get_tags(repository=repo).get("tags", [])
|
|
50
|
+
query_results = process.extract(token, tags, limit=2)
|
|
51
|
+
matching_tuples = [
|
|
52
|
+
(version, score) for version, score in query_results if score > 88
|
|
53
|
+
]
|
|
54
|
+
if len(matching_tuples) > 0:
|
|
55
|
+
response.append(f"{repo}: {matching_tuples}")
|
|
56
|
+
logger.info(f"{repo}: {matching_tuples}")
|
|
57
|
+
except Exception as e:
|
|
58
|
+
logger.info(e)
|
|
59
|
+
pass
|
|
60
|
+
return response
|
|
61
|
+
|
|
62
|
+
def count_images(self, repository):
|
|
63
|
+
tags = self.get_tags(repository)
|
|
64
|
+
if tags:
|
|
65
|
+
return len(tags.get("tags", []))
|
|
66
|
+
return 0
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@click.group()
|
|
70
|
+
@click.option(
|
|
71
|
+
"--registry-url",
|
|
72
|
+
default="",
|
|
73
|
+
help="URL of the Docker registry",
|
|
74
|
+
)
|
|
75
|
+
@click.pass_context
|
|
76
|
+
def registry(ctx, registry_url):
|
|
77
|
+
"""registry utility - use this to interact with the mcli Docker registry."""
|
|
78
|
+
ctx.obj = DockerClient(registry_url)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@registry.command()
|
|
82
|
+
@click.pass_context
|
|
83
|
+
def catalog(ctx):
|
|
84
|
+
"""Fetch the catalog of repositories."""
|
|
85
|
+
client = ctx.obj
|
|
86
|
+
catalog = client.get_catalog()
|
|
87
|
+
if catalog:
|
|
88
|
+
click.echo("Catalog:")
|
|
89
|
+
for repo in catalog.get("repositories", []):
|
|
90
|
+
click.echo(f" - {repo}")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@registry.command()
|
|
94
|
+
@click.argument("repository")
|
|
95
|
+
@click.option("--tag-name")
|
|
96
|
+
@click.pass_context
|
|
97
|
+
def tags(ctx, repository, tag_name):
|
|
98
|
+
"""Fetch the tags for a given repository."""
|
|
99
|
+
client = ctx.obj
|
|
100
|
+
tags = client.get_tags(repository)
|
|
101
|
+
if tag_name:
|
|
102
|
+
logger.info(tag_name)
|
|
103
|
+
else:
|
|
104
|
+
click.echo(f"Tags for repository '{repository}':")
|
|
105
|
+
for tag in tags.get("tags", []):
|
|
106
|
+
click.echo(f" - {tag}")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@registry.command(name="search-tags")
|
|
110
|
+
@click.argument("repository")
|
|
111
|
+
@click.option("--tag-name")
|
|
112
|
+
@click.pass_context
|
|
113
|
+
def search_tags(ctx, repository, tag_name):
|
|
114
|
+
"""Fetch the tags for a given repository."""
|
|
115
|
+
client = ctx.obj
|
|
116
|
+
tags = client.get_tags(repository)
|
|
117
|
+
if tag_name:
|
|
118
|
+
logger.info(tag_name)
|
|
119
|
+
else:
|
|
120
|
+
click.echo(f"Tags for repository '{repository}':")
|
|
121
|
+
for tag in tags.get("tags", []):
|
|
122
|
+
click.echo(f" - {tag}")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@registry.command()
|
|
126
|
+
@click.argument("repository")
|
|
127
|
+
@click.pass_context
|
|
128
|
+
def search(ctx, repository):
|
|
129
|
+
"""Search for a repository by name."""
|
|
130
|
+
client = ctx.obj
|
|
131
|
+
results = client.search_repository(repository)
|
|
132
|
+
if results:
|
|
133
|
+
click.echo(f"Search results for '{repository}':")
|
|
134
|
+
for repo in results:
|
|
135
|
+
click.echo(f" - {repo}")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@registry.command()
|
|
139
|
+
@click.argument("repository")
|
|
140
|
+
@click.argument("tag")
|
|
141
|
+
@click.pass_context
|
|
142
|
+
def image_info(ctx, repository, tag):
|
|
143
|
+
"""Get detailed information about a specific image."""
|
|
144
|
+
client = ctx.obj
|
|
145
|
+
info = client.get_image_info(repository, tag)
|
|
146
|
+
if info:
|
|
147
|
+
click.echo(f"Image info for {repository}:{tag}:")
|
|
148
|
+
click.echo(info)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@registry.command()
|
|
152
|
+
@click.argument("repository")
|
|
153
|
+
@click.pass_context
|
|
154
|
+
def count(ctx, repository):
|
|
155
|
+
"""Count the number of tags/images in a repository."""
|
|
156
|
+
client = ctx.obj
|
|
157
|
+
count = client.count_images(repository)
|
|
158
|
+
click.echo(f"Number of tags in repository '{repository}': {count}")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@registry.command()
|
|
162
|
+
@click.argument("repository")
|
|
163
|
+
@click.argument("tag")
|
|
164
|
+
@click.pass_context
|
|
165
|
+
def pull(ctx, repository, tag):
|
|
166
|
+
"""Pull an image from the registry."""
|
|
167
|
+
client = ctx.obj
|
|
168
|
+
image = client.pull_image(repository, tag)
|
|
169
|
+
if image:
|
|
170
|
+
click.echo(f"Pulled image {repository}:{tag}")
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
# TODO: Implement the pull_image method in DockerClient
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
@registry.command("fuzzy-search")
|
|
177
|
+
@click.argument("token")
|
|
178
|
+
@click.pass_context
|
|
179
|
+
def fuzzy_search(ctx, token):
|
|
180
|
+
return ctx.obj.search_all_repositories(token)
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from openai import OpenAI
|
|
7
|
+
from openpyxl.styles import Alignment
|
|
8
|
+
|
|
9
|
+
from mcli.lib.logger.logger import get_logger
|
|
10
|
+
from mcli.lib.shell.shell import get_shell_script_path, shell_exec
|
|
11
|
+
|
|
12
|
+
logger = get_logger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@click.group(name="repo")
|
|
16
|
+
def repo():
|
|
17
|
+
"""repo utility - use this to interact with git and relevant utilities"""
|
|
18
|
+
click.echo("repo")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@repo.command()
|
|
22
|
+
@click.argument("path")
|
|
23
|
+
def analyze(path: str):
|
|
24
|
+
"""Provides a source lines of code analysis for a given pkg path"""
|
|
25
|
+
_analyze(path)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _analyze(path: str):
|
|
29
|
+
# Define the directory to analyze
|
|
30
|
+
repo_directory = path
|
|
31
|
+
|
|
32
|
+
# Define the file extensions to count
|
|
33
|
+
file_extensions = {
|
|
34
|
+
"Java": ".java",
|
|
35
|
+
"Python": ".py",
|
|
36
|
+
"js": ".js",
|
|
37
|
+
"HTML": ".html",
|
|
38
|
+
"mcli": ".mcli",
|
|
39
|
+
"ts": ".ts",
|
|
40
|
+
"tsx": ".tsx",
|
|
41
|
+
"JSON": ".json",
|
|
42
|
+
"scss": ".scss",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# Define the files and extensions to exclude
|
|
46
|
+
exclude_files = [
|
|
47
|
+
"node_modules",
|
|
48
|
+
"resources",
|
|
49
|
+
"provision",
|
|
50
|
+
"jenkins",
|
|
51
|
+
"git_hooks",
|
|
52
|
+
"deps",
|
|
53
|
+
"submodules",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
exclude_extensions = [".log", ".tmp", ".md", ".yml", ".sh", ".txt"]
|
|
57
|
+
|
|
58
|
+
# Function to apply formatting to Excel sheets
|
|
59
|
+
def format_excel_sheets(writer, sheet_name):
|
|
60
|
+
workbook = writer.book
|
|
61
|
+
worksheet = workbook[sheet_name]
|
|
62
|
+
for col in worksheet.columns:
|
|
63
|
+
max_length = 0
|
|
64
|
+
column = col[0].column_letter # Get the column name
|
|
65
|
+
for cell in col:
|
|
66
|
+
try:
|
|
67
|
+
if len(str(cell.value)) > max_length:
|
|
68
|
+
max_length = len(cell.value)
|
|
69
|
+
except Exception as e:
|
|
70
|
+
logger.info(e)
|
|
71
|
+
pass
|
|
72
|
+
adjusted_width = max_length + 2
|
|
73
|
+
worksheet.column_dimensions[column].width = adjusted_width
|
|
74
|
+
for cell in col:
|
|
75
|
+
cell.alignment = Alignment(wrap_text=True)
|
|
76
|
+
|
|
77
|
+
# Function to count files and lines of code for a given directory
|
|
78
|
+
def count_files_and_sloc(directory, extensions, exclude_files, exclude_extensions):
|
|
79
|
+
sloc_count = {ext: {"files": 0, "sloc": 0, "details": []} for ext in extensions}
|
|
80
|
+
for root, dirs, files in os.walk(directory):
|
|
81
|
+
# Exclude specified directories
|
|
82
|
+
dirs[:] = [d for d in dirs if d not in exclude_files]
|
|
83
|
+
for file in files:
|
|
84
|
+
# Exclude specified files and extensions
|
|
85
|
+
if any(file.endswith(ext) for ext in exclude_extensions) or file in exclude_files:
|
|
86
|
+
continue
|
|
87
|
+
for ext, ext_name in extensions.items():
|
|
88
|
+
if file.endswith(ext_name):
|
|
89
|
+
sloc_count[ext]["files"] += 1
|
|
90
|
+
file_path = os.path.join(root, file)
|
|
91
|
+
with open(file_path, "r", errors="ignore") as f:
|
|
92
|
+
sloc = sum(1 for line in f if line.strip() and line.strip() != "\n")
|
|
93
|
+
sloc_count[ext]["sloc"] += sloc
|
|
94
|
+
sloc_count[ext]["details"].append(
|
|
95
|
+
{"filename": file, "filepath": file_path, "sloc": sloc}
|
|
96
|
+
)
|
|
97
|
+
return sloc_count
|
|
98
|
+
|
|
99
|
+
# Function to write results to CSV and Excel files
|
|
100
|
+
def write_results_to_files(sloc_counts, csv_file, excel_file):
|
|
101
|
+
summary_data = []
|
|
102
|
+
# Write the results to a CSV file
|
|
103
|
+
with open(csv_file, mode="w", newline="") as file:
|
|
104
|
+
writer = csv.writer(file)
|
|
105
|
+
writer.writerow(["File Type", "Number of Files", "SLOC"])
|
|
106
|
+
for ext, counts in sloc_counts.items():
|
|
107
|
+
writer.writerow([ext, counts["files"], counts["sloc"]])
|
|
108
|
+
summary_data.append([ext, counts["files"], counts["sloc"]])
|
|
109
|
+
|
|
110
|
+
# Write the detailed results to an Excel file
|
|
111
|
+
with pd.ExcelWriter(excel_file, engine="openpyxl") as writer:
|
|
112
|
+
# Write summary as the first sheet
|
|
113
|
+
df_summary = pd.DataFrame(
|
|
114
|
+
summary_data, columns=["File Type", "Number of Files", "SLOC"]
|
|
115
|
+
)
|
|
116
|
+
df_summary.to_excel(writer, sheet_name="Summary", index=False)
|
|
117
|
+
format_excel_sheets(writer, "Summary")
|
|
118
|
+
|
|
119
|
+
# Write details for each file type
|
|
120
|
+
for ext, counts in sloc_counts.items():
|
|
121
|
+
df = pd.DataFrame(counts["details"])
|
|
122
|
+
df.to_excel(writer, sheet_name=ext, index=False)
|
|
123
|
+
format_excel_sheets(writer, ext)
|
|
124
|
+
|
|
125
|
+
logger.info(f"\nResults have been written to {csv_file} and {excel_file}")
|
|
126
|
+
|
|
127
|
+
# Generate the SLOC counts
|
|
128
|
+
sloc_counts = count_files_and_sloc(
|
|
129
|
+
repo_directory, file_extensions, exclude_files, exclude_extensions
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# logger.info the results in a tabular format
|
|
133
|
+
logger.info("Source Lines of Code (SLOC)")
|
|
134
|
+
logger.info("-" * 50)
|
|
135
|
+
logger.info(f"{'File Type':<10}{'Number of Files':<20}{'SLOC':<10}")
|
|
136
|
+
logger.info("-" * 50)
|
|
137
|
+
for ext, counts in sloc_counts.items():
|
|
138
|
+
logger.info(f"{ext:<10}{counts['files']:<20}{counts['sloc']:<10}")
|
|
139
|
+
|
|
140
|
+
# Define the output file names
|
|
141
|
+
csv_file = "sloc_report.csv"
|
|
142
|
+
excel_file = "sloc_report.xlsx"
|
|
143
|
+
|
|
144
|
+
# Write the results to CSV and Excel files
|
|
145
|
+
write_results_to_files(sloc_counts, csv_file, excel_file)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@repo.command(name="wt")
|
|
149
|
+
def worktree():
|
|
150
|
+
"""Create and manage worktrees"""
|
|
151
|
+
scripts_path = get_shell_script_path("repo", __file__)
|
|
152
|
+
shell_exec(scripts_path, "wt")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@repo.command(name="commit")
|
|
156
|
+
def commit():
|
|
157
|
+
"""Edit commits to a repository"""
|
|
158
|
+
click.echo("commit")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@repo.command(name="revert")
|
|
162
|
+
def revert():
|
|
163
|
+
"""Create and manage worktrees"""
|
|
164
|
+
scripts_path = get_shell_script_path("repo", __file__)
|
|
165
|
+
shell_exec(scripts_path, "revert")
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@repo.command(name="migration-loe")
|
|
169
|
+
@click.argument("branch-a")
|
|
170
|
+
@click.argument("branch-b")
|
|
171
|
+
def loe(branch_a: str, branch_b: str):
|
|
172
|
+
"""Create and manage worktrees"""
|
|
173
|
+
scripts_path = get_shell_script_path("repo", __file__)
|
|
174
|
+
result = shell_exec(scripts_path, "migration_loe", branch_a, branch_b)
|
|
175
|
+
# Assume result['result'] contains the output from the shell script
|
|
176
|
+
if result is None:
|
|
177
|
+
return
|
|
178
|
+
# Extract the list of files from the result
|
|
179
|
+
logger.info(result)
|
|
180
|
+
return
|
|
181
|
+
file_list = result.get("result", [])
|
|
182
|
+
|
|
183
|
+
# Format the file list as a string for the prompt
|
|
184
|
+
file_summary = "\n".join(file_list)
|
|
185
|
+
|
|
186
|
+
# Construct the prompt for GPT-4
|
|
187
|
+
prompt = f"""
|
|
188
|
+
You are an expert in planning engineering projects, estimating level of effort, and a granular approach to changes for each item in an enmerated list. Analyze the following list of files to categorize the changes (e.g., UI updates, backend changes, configuration edits) and provide a detailed summary for a migration effort. Enumerate the changes in each file. Your output should also include a suggested categorization of the changes such that they can be used by the migration team to create issues in jira and track progress. The categorization must include every single file provided and report each one of them back in a category.
|
|
189
|
+
|
|
190
|
+
{file_summary}
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
try:
|
|
194
|
+
# Initialize the OpenAI client - API key from environment
|
|
195
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
|
196
|
+
if not api_key:
|
|
197
|
+
logger.error("OPENAI_API_KEY environment variable not set")
|
|
198
|
+
return
|
|
199
|
+
|
|
200
|
+
client = OpenAI(api_key=api_key)
|
|
201
|
+
|
|
202
|
+
# Call the GPT-4 model using the client
|
|
203
|
+
chat_completion = client.chat.completions.create(
|
|
204
|
+
messages=[
|
|
205
|
+
{
|
|
206
|
+
"role": "user",
|
|
207
|
+
"content": prompt,
|
|
208
|
+
}
|
|
209
|
+
],
|
|
210
|
+
model="gpt-4",
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
# Access the response content correctly
|
|
214
|
+
analysis = chat_completion.choices[0].message.content
|
|
215
|
+
logger.info("Analysis of changes:")
|
|
216
|
+
logger.info(analysis)
|
|
217
|
+
|
|
218
|
+
except Exception as e:
|
|
219
|
+
logger.info(f"An error occurred while calling OpenAI API: {e}")
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
if __name__ == "__main__":
|
|
223
|
+
repo()
|