mcli-framework 7.4.0__py3-none-any.whl → 7.5.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/lib/auth/aws_manager.py +9 -64
- mcli/lib/auth/azure_manager.py +9 -64
- mcli/lib/auth/credential_manager.py +70 -1
- mcli/lib/auth/gcp_manager.py +11 -64
- mcli/ml/dashboard/app.py +6 -39
- mcli/ml/dashboard/app_integrated.py +23 -101
- mcli/ml/dashboard/app_supabase.py +8 -57
- mcli/ml/dashboard/app_training.py +9 -11
- mcli/ml/dashboard/common.py +167 -0
- mcli/ml/dashboard/pages/cicd.py +4 -4
- mcli/ml/dashboard/pages/debug_dependencies.py +99 -57
- mcli/ml/dashboard/pages/gravity_viz.py +265 -47
- mcli/ml/dashboard/pages/predictions_enhanced.py +4 -2
- mcli/ml/dashboard/pages/scrapers_and_logs.py +3 -3
- mcli/ml/dashboard/styles.py +55 -0
- mcli/self/self_cmd.py +12 -806
- {mcli_framework-7.4.0.dist-info → mcli_framework-7.5.0.dist-info}/METADATA +1 -3
- {mcli_framework-7.4.0.dist-info → mcli_framework-7.5.0.dist-info}/RECORD +23 -84
- mcli/__init__.py +0 -160
- mcli/__main__.py +0 -14
- mcli/app/__init__.py +0 -23
- mcli/app/model/__init__.py +0 -0
- mcli/app/video/__init__.py +0 -5
- mcli/chat/__init__.py +0 -34
- mcli/lib/__init__.py +0 -0
- mcli/lib/api/__init__.py +0 -0
- mcli/lib/auth/__init__.py +0 -1
- mcli/lib/config/__init__.py +0 -1
- mcli/lib/erd/__init__.py +0 -25
- mcli/lib/files/__init__.py +0 -0
- mcli/lib/fs/__init__.py +0 -1
- mcli/lib/logger/__init__.py +0 -3
- mcli/lib/performance/__init__.py +0 -17
- mcli/lib/pickles/__init__.py +0 -1
- mcli/lib/shell/__init__.py +0 -0
- mcli/lib/toml/__init__.py +0 -1
- mcli/lib/watcher/__init__.py +0 -0
- mcli/ml/__init__.py +0 -16
- mcli/ml/api/__init__.py +0 -30
- mcli/ml/api/routers/__init__.py +0 -27
- mcli/ml/auth/__init__.py +0 -45
- mcli/ml/backtesting/__init__.py +0 -39
- mcli/ml/cli/__init__.py +0 -5
- mcli/ml/config/__init__.py +0 -33
- mcli/ml/configs/__init__.py +0 -16
- mcli/ml/dashboard/__init__.py +0 -12
- mcli/ml/dashboard/components/__init__.py +0 -7
- mcli/ml/dashboard/pages/__init__.py +0 -6
- mcli/ml/data_ingestion/__init__.py +0 -39
- mcli/ml/database/__init__.py +0 -47
- mcli/ml/experimentation/__init__.py +0 -29
- mcli/ml/features/__init__.py +0 -39
- mcli/ml/mlops/__init__.py +0 -33
- mcli/ml/models/__init__.py +0 -94
- mcli/ml/monitoring/__init__.py +0 -25
- mcli/ml/optimization/__init__.py +0 -27
- mcli/ml/predictions/__init__.py +0 -5
- mcli/ml/preprocessing/__init__.py +0 -28
- mcli/ml/scripts/__init__.py +0 -1
- mcli/ml/trading/__init__.py +0 -66
- mcli/ml/training/__init__.py +0 -10
- mcli/mygroup/__init__.py +0 -3
- mcli/public/__init__.py +0 -1
- mcli/public/commands/__init__.py +0 -2
- mcli/self/__init__.py +0 -3
- mcli/workflow/__init__.py +0 -0
- mcli/workflow/daemon/__init__.py +0 -15
- mcli/workflow/dashboard/__init__.py +0 -5
- mcli/workflow/docker/__init__.py +0 -0
- mcli/workflow/file/__init__.py +0 -0
- mcli/workflow/gcloud/__init__.py +0 -1
- mcli/workflow/git_commit/__init__.py +0 -0
- mcli/workflow/interview/__init__.py +0 -0
- mcli/workflow/politician_trading/__init__.py +0 -4
- mcli/workflow/registry/__init__.py +0 -0
- mcli/workflow/repo/__init__.py +0 -0
- mcli/workflow/scheduler/__init__.py +0 -25
- mcli/workflow/search/__init__.py +0 -0
- mcli/workflow/sync/__init__.py +0 -5
- mcli/workflow/videos/__init__.py +0 -1
- mcli/workflow/wakatime/__init__.py +0 -80
- /mcli/ml/dashboard/{pages/overview.py → overview.py} +0 -0
- {mcli_framework-7.4.0.dist-info → mcli_framework-7.5.0.dist-info}/WHEEL +0 -0
- {mcli_framework-7.4.0.dist-info → mcli_framework-7.5.0.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.4.0.dist-info → mcli_framework-7.5.0.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.4.0.dist-info → mcli_framework-7.5.0.dist-info}/top_level.txt +0 -0
mcli/lib/auth/aws_manager.py
CHANGED
|
@@ -1,84 +1,29 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import Optional
|
|
3
2
|
|
|
4
3
|
from mcli.lib.config import DEV_SECRETS_ROOT
|
|
5
4
|
from mcli.lib.fs import get_absolute_path
|
|
6
5
|
from mcli.lib.logger.logger import get_logger
|
|
7
6
|
|
|
8
|
-
from .credential_manager import
|
|
7
|
+
from .credential_manager import CloudProviderManager
|
|
9
8
|
|
|
10
9
|
logger = get_logger(__name__)
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
class AwsManager(
|
|
12
|
+
class AwsManager(CloudProviderManager):
|
|
14
13
|
"""
|
|
15
|
-
|
|
14
|
+
AWS credential manager for handling authentication tokens and storage credentials.
|
|
15
|
+
Inherits common token management from CloudProviderManager.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Initialize AwsManager with a specific configuration filename.
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
app_name (str, optional): Name of the application. Defaults to "mcli".
|
|
24
|
-
"""
|
|
25
|
-
super().__init__(app_name, config_filename="mcli.token.config.json")
|
|
26
|
-
|
|
27
|
-
def save_token(self, token: str):
|
|
18
|
+
@staticmethod
|
|
19
|
+
def persist_aws_storage_creds(access_key, secret_key):
|
|
28
20
|
"""
|
|
29
|
-
|
|
21
|
+
Persist AWS storage credentials to file.
|
|
30
22
|
|
|
31
23
|
Args:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Raises:
|
|
35
|
-
ValueError: If token is empty or not a string.
|
|
36
|
-
"""
|
|
37
|
-
if not token or not isinstance(token, str):
|
|
38
|
-
raise ValueError("Token must be a non-empty string")
|
|
39
|
-
|
|
40
|
-
try:
|
|
41
|
-
self.update_config("auth_token", token)
|
|
42
|
-
except Exception as e:
|
|
43
|
-
raise Exception(f"Failed to save token: {str(e)}")
|
|
44
|
-
|
|
45
|
-
def get_token(self) -> Optional[str]:
|
|
24
|
+
access_key (str): AWS access key.
|
|
25
|
+
secret_key (str): AWS secret key.
|
|
46
26
|
"""
|
|
47
|
-
Retrieve the stored authentication token.
|
|
48
|
-
|
|
49
|
-
Returns:
|
|
50
|
-
Optional[str]: Stored authentication token or None if not found.
|
|
51
|
-
"""
|
|
52
|
-
try:
|
|
53
|
-
logger.info("getting token")
|
|
54
|
-
return self.get_config_value("auth_token")
|
|
55
|
-
except Exception as e:
|
|
56
|
-
logger.info(f"Warning: Error retrieving token: {str(e)}")
|
|
57
|
-
return None
|
|
58
|
-
|
|
59
|
-
def clear_token(self):
|
|
60
|
-
"""
|
|
61
|
-
Clear the stored authentication token.
|
|
62
|
-
Uses the base class clear_config method.
|
|
63
|
-
"""
|
|
64
|
-
self.clear_config()
|
|
65
|
-
|
|
66
|
-
def get_url(self) -> Optional[str]:
|
|
67
|
-
"""
|
|
68
|
-
Retrieve environment URL from configuration.
|
|
69
|
-
|
|
70
|
-
Returns:
|
|
71
|
-
Optional[str]: Stored environment URL or None if not found.
|
|
72
|
-
"""
|
|
73
|
-
try:
|
|
74
|
-
logger.info("getting url")
|
|
75
|
-
return self.get_config_value("env_url")
|
|
76
|
-
except Exception as e:
|
|
77
|
-
logger.info(f"Warning: Error retrieving environment URL: {str(e)}")
|
|
78
|
-
return None
|
|
79
|
-
|
|
80
|
-
@staticmethod
|
|
81
|
-
def persist_aws_storage_creds(access_key, secret_key):
|
|
82
27
|
filepath = get_absolute_path(DEV_SECRETS_ROOT + "aws/aws.json")
|
|
83
28
|
with open(filepath, "w") as f:
|
|
84
29
|
json.dump({"access_key": access_key, "secret_key": secret_key}, f)
|
mcli/lib/auth/azure_manager.py
CHANGED
|
@@ -1,84 +1,29 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import Optional
|
|
3
2
|
|
|
4
3
|
from mcli.lib.config import DEV_SECRETS_ROOT
|
|
5
4
|
from mcli.lib.fs import get_absolute_path
|
|
6
5
|
from mcli.lib.logger.logger import get_logger
|
|
7
6
|
|
|
8
|
-
from .credential_manager import
|
|
7
|
+
from .credential_manager import CloudProviderManager
|
|
9
8
|
|
|
10
9
|
logger = get_logger(__name__)
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
class AzureManager(
|
|
12
|
+
class AzureManager(CloudProviderManager):
|
|
14
13
|
"""
|
|
15
|
-
|
|
14
|
+
Azure credential manager for handling authentication tokens and storage credentials.
|
|
15
|
+
Inherits common token management from CloudProviderManager.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Initialize GcpManager with a specific configuration filename.
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
app_name (str, optional): Name of the application. Defaults to "mcli".
|
|
24
|
-
"""
|
|
25
|
-
super().__init__(app_name, config_filename="mcli.token.config.json")
|
|
26
|
-
|
|
27
|
-
def save_token(self, token: str):
|
|
18
|
+
@staticmethod
|
|
19
|
+
def persist_azure_storage_creds(account_name, access_key):
|
|
28
20
|
"""
|
|
29
|
-
|
|
21
|
+
Persist Azure storage credentials to file.
|
|
30
22
|
|
|
31
23
|
Args:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Raises:
|
|
35
|
-
ValueError: If token is empty or not a string.
|
|
36
|
-
"""
|
|
37
|
-
if not token or not isinstance(token, str):
|
|
38
|
-
raise ValueError("Token must be a non-empty string")
|
|
39
|
-
|
|
40
|
-
try:
|
|
41
|
-
self.update_config("auth_token", token)
|
|
42
|
-
except Exception as e:
|
|
43
|
-
raise Exception(f"Failed to save token: {str(e)}")
|
|
44
|
-
|
|
45
|
-
def get_token(self) -> Optional[str]:
|
|
24
|
+
account_name (str): Azure storage account name.
|
|
25
|
+
access_key (str): Azure storage access key.
|
|
46
26
|
"""
|
|
47
|
-
Retrieve the stored authentication token.
|
|
48
|
-
|
|
49
|
-
Returns:
|
|
50
|
-
Optional[str]: Stored authentication token or None if not found.
|
|
51
|
-
"""
|
|
52
|
-
try:
|
|
53
|
-
logger.info("getting token")
|
|
54
|
-
return self.get_config_value("auth_token")
|
|
55
|
-
except Exception as e:
|
|
56
|
-
logger.info(f"Warning: Error retrieving token: {str(e)}")
|
|
57
|
-
return None
|
|
58
|
-
|
|
59
|
-
def clear_token(self):
|
|
60
|
-
"""
|
|
61
|
-
Clear the stored authentication token.
|
|
62
|
-
Uses the base class clear_config method.
|
|
63
|
-
"""
|
|
64
|
-
self.clear_config()
|
|
65
|
-
|
|
66
|
-
def get_url(self) -> Optional[str]:
|
|
67
|
-
"""
|
|
68
|
-
Retrieve environment URL from configuration.
|
|
69
|
-
|
|
70
|
-
Returns:
|
|
71
|
-
Optional[str]: Stored environment URL or None if not found.
|
|
72
|
-
"""
|
|
73
|
-
try:
|
|
74
|
-
logger.info("getting url")
|
|
75
|
-
return self.get_config_value("env_url")
|
|
76
|
-
except Exception as e:
|
|
77
|
-
logger.info(f"Warning: Error retrieving environment URL: {str(e)}")
|
|
78
|
-
return None
|
|
79
|
-
|
|
80
|
-
@staticmethod
|
|
81
|
-
def persist_azure_storage_creds(account_name, access_key):
|
|
82
27
|
filepath = get_absolute_path(DEV_SECRETS_ROOT + "azure/azure.json")
|
|
83
28
|
with open(filepath, "w") as f:
|
|
84
29
|
json.dump(
|
|
@@ -189,4 +189,73 @@ class CredentialManager:
|
|
|
189
189
|
return key_b64
|
|
190
190
|
|
|
191
191
|
|
|
192
|
-
|
|
192
|
+
class CloudProviderManager(CredentialManager):
|
|
193
|
+
"""
|
|
194
|
+
Abstract base class for cloud provider credential managers.
|
|
195
|
+
Provides common token and URL management functionality for AWS, GCP, and Azure.
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
def __init__(self, app_name: str = "mcli"):
|
|
199
|
+
"""
|
|
200
|
+
Initialize CloudProviderManager with token configuration filename.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
app_name (str, optional): Name of the application. Defaults to "mcli".
|
|
204
|
+
"""
|
|
205
|
+
super().__init__(app_name, config_filename="mcli.token.config.json")
|
|
206
|
+
|
|
207
|
+
def save_token(self, token: str):
|
|
208
|
+
"""
|
|
209
|
+
Save authentication token to configuration.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
token (str): Authentication token to save.
|
|
213
|
+
|
|
214
|
+
Raises:
|
|
215
|
+
ValueError: If token is empty or not a string.
|
|
216
|
+
"""
|
|
217
|
+
if not token or not isinstance(token, str):
|
|
218
|
+
raise ValueError("Token must be a non-empty string")
|
|
219
|
+
|
|
220
|
+
try:
|
|
221
|
+
self.update_config("auth_token", token)
|
|
222
|
+
except Exception as e:
|
|
223
|
+
raise Exception(f"Failed to save token: {str(e)}")
|
|
224
|
+
|
|
225
|
+
def get_token(self) -> Optional[str]:
|
|
226
|
+
"""
|
|
227
|
+
Retrieve the stored authentication token.
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
Optional[str]: Stored authentication token or None if not found.
|
|
231
|
+
"""
|
|
232
|
+
try:
|
|
233
|
+
logger.info("getting token")
|
|
234
|
+
return self.get_config_value("auth_token")
|
|
235
|
+
except Exception as e:
|
|
236
|
+
logger.info(f"Warning: Error retrieving token: {str(e)}")
|
|
237
|
+
return None
|
|
238
|
+
|
|
239
|
+
def clear_token(self):
|
|
240
|
+
"""
|
|
241
|
+
Clear the stored authentication token.
|
|
242
|
+
Uses the base class clear_config method.
|
|
243
|
+
"""
|
|
244
|
+
self.clear_config()
|
|
245
|
+
|
|
246
|
+
def get_url(self) -> Optional[str]:
|
|
247
|
+
"""
|
|
248
|
+
Retrieve environment URL from configuration.
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
Optional[str]: Stored environment URL or None if not found.
|
|
252
|
+
"""
|
|
253
|
+
try:
|
|
254
|
+
logger.info("getting url")
|
|
255
|
+
return self.get_config_value("env_url")
|
|
256
|
+
except Exception as e:
|
|
257
|
+
logger.info(f"Warning: Error retrieving environment URL: {str(e)}")
|
|
258
|
+
return None
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
__all__ = ["CredentialManager", "CloudProviderManager"]
|
mcli/lib/auth/gcp_manager.py
CHANGED
|
@@ -1,84 +1,31 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import Optional
|
|
3
2
|
|
|
4
3
|
from mcli.lib.config import DEV_SECRETS_ROOT
|
|
5
4
|
from mcli.lib.fs import get_absolute_path
|
|
6
5
|
from mcli.lib.logger.logger import get_logger
|
|
7
6
|
|
|
8
|
-
from .credential_manager import
|
|
7
|
+
from .credential_manager import CloudProviderManager
|
|
9
8
|
|
|
10
9
|
logger = get_logger(__name__)
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
class GcpManager(
|
|
12
|
+
class GcpManager(CloudProviderManager):
|
|
14
13
|
"""
|
|
15
|
-
|
|
14
|
+
GCP credential manager for handling authentication tokens and storage credentials.
|
|
15
|
+
Inherits common token management from CloudProviderManager.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Initialize GcpManager with a specific configuration filename.
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
app_name (str, optional): Name of the application. Defaults to "mcli".
|
|
24
|
-
"""
|
|
25
|
-
super().__init__(app_name, config_filename="mcli.token.config.json")
|
|
26
|
-
|
|
27
|
-
def save_token(self, token: str):
|
|
18
|
+
@staticmethod
|
|
19
|
+
def persist_gcp_storage_creds(account_id, account_email, access_key, secret_key):
|
|
28
20
|
"""
|
|
29
|
-
|
|
21
|
+
Persist GCP storage credentials to file.
|
|
30
22
|
|
|
31
23
|
Args:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"""
|
|
37
|
-
if not token or not isinstance(token, str):
|
|
38
|
-
raise ValueError("Token must be a non-empty string")
|
|
39
|
-
|
|
40
|
-
try:
|
|
41
|
-
self.update_config("auth_token", token)
|
|
42
|
-
except Exception as e:
|
|
43
|
-
raise Exception(f"Failed to save token: {str(e)}")
|
|
44
|
-
|
|
45
|
-
def get_token(self) -> Optional[str]:
|
|
24
|
+
account_id (str): GCP account ID.
|
|
25
|
+
account_email (str): GCP account email.
|
|
26
|
+
access_key (str): GCP access key.
|
|
27
|
+
secret_key (str): GCP secret key.
|
|
46
28
|
"""
|
|
47
|
-
Retrieve the stored authentication token.
|
|
48
|
-
|
|
49
|
-
Returns:
|
|
50
|
-
Optional[str]: Stored authentication token or None if not found.
|
|
51
|
-
"""
|
|
52
|
-
try:
|
|
53
|
-
logger.info("getting token")
|
|
54
|
-
return self.get_config_value("auth_token")
|
|
55
|
-
except Exception as e:
|
|
56
|
-
logger.info(f"Warning: Error retrieving token: {str(e)}")
|
|
57
|
-
return None
|
|
58
|
-
|
|
59
|
-
def clear_token(self):
|
|
60
|
-
"""
|
|
61
|
-
Clear the stored authentication token.
|
|
62
|
-
Uses the base class clear_config method.
|
|
63
|
-
"""
|
|
64
|
-
self.clear_config()
|
|
65
|
-
|
|
66
|
-
def get_url(self) -> Optional[str]:
|
|
67
|
-
"""
|
|
68
|
-
Retrieve environment URL from configuration.
|
|
69
|
-
|
|
70
|
-
Returns:
|
|
71
|
-
Optional[str]: Stored environment URL or None if not found.
|
|
72
|
-
"""
|
|
73
|
-
try:
|
|
74
|
-
logger.info("getting url")
|
|
75
|
-
return self.get_config_value("env_url")
|
|
76
|
-
except Exception as e:
|
|
77
|
-
logger.info(f"Warning: Error retrieving environment URL: {str(e)}")
|
|
78
|
-
return None
|
|
79
|
-
|
|
80
|
-
@staticmethod
|
|
81
|
-
def persist_gcp_storage_creds(account_id, account_email, access_key, secret_key):
|
|
82
29
|
filepath = get_absolute_path(DEV_SECRETS_ROOT + "gcp/gcp.json")
|
|
83
30
|
with open(filepath, "w") as f:
|
|
84
31
|
json.dump(
|
mcli/ml/dashboard/app.py
CHANGED
|
@@ -25,47 +25,14 @@ from mcli.ml.database.models import (
|
|
|
25
25
|
User,
|
|
26
26
|
)
|
|
27
27
|
from mcli.ml.database.session import SessionLocal
|
|
28
|
+
from mcli.ml.dashboard.common import setup_page_config
|
|
29
|
+
from mcli.ml.dashboard.styles import apply_dashboard_styles
|
|
28
30
|
|
|
29
|
-
# Page config
|
|
30
|
-
|
|
31
|
-
page_title="MCLI ML Dashboard", page_icon="📊", layout="wide", initial_sidebar_state="expanded"
|
|
32
|
-
)
|
|
31
|
+
# Page config - must be first
|
|
32
|
+
setup_page_config(page_title="MCLI ML Dashboard")
|
|
33
33
|
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
"""
|
|
37
|
-
<style>
|
|
38
|
-
.metric-card {
|
|
39
|
-
background-color: #f0f2f6;
|
|
40
|
-
padding: 1rem;
|
|
41
|
-
border-radius: 0.5rem;
|
|
42
|
-
border-left: 4px solid #1f77b4;
|
|
43
|
-
}
|
|
44
|
-
.alert-success {
|
|
45
|
-
background-color: #d4edda;
|
|
46
|
-
border: 1px solid #c3e6cb;
|
|
47
|
-
color: #155724;
|
|
48
|
-
padding: 0.75rem;
|
|
49
|
-
border-radius: 0.25rem;
|
|
50
|
-
}
|
|
51
|
-
.alert-warning {
|
|
52
|
-
background-color: #fff3cd;
|
|
53
|
-
border: 1px solid #ffeaa7;
|
|
54
|
-
color: #856404;
|
|
55
|
-
padding: 0.75rem;
|
|
56
|
-
border-radius: 0.25rem;
|
|
57
|
-
}
|
|
58
|
-
.alert-danger {
|
|
59
|
-
background-color: #f8d7da;
|
|
60
|
-
border: 1px solid #f5c6cb;
|
|
61
|
-
color: #721c24;
|
|
62
|
-
padding: 0.75rem;
|
|
63
|
-
border-radius: 0.25rem;
|
|
64
|
-
}
|
|
65
|
-
</style>
|
|
66
|
-
""",
|
|
67
|
-
unsafe_allow_html=True,
|
|
68
|
-
)
|
|
34
|
+
# Apply standard dashboard styles
|
|
35
|
+
apply_dashboard_styles()
|
|
69
36
|
|
|
70
37
|
|
|
71
38
|
@st.cache_data(ttl=30)
|
|
@@ -6,48 +6,37 @@ import logging
|
|
|
6
6
|
import os
|
|
7
7
|
import pickle
|
|
8
8
|
import subprocess
|
|
9
|
-
import warnings
|
|
10
9
|
from datetime import datetime, timedelta
|
|
11
10
|
from pathlib import Path
|
|
12
11
|
from typing import List
|
|
13
12
|
|
|
14
13
|
import numpy as np
|
|
15
14
|
|
|
16
|
-
# Suppress
|
|
17
|
-
|
|
18
|
-
warnings.filterwarnings("ignore", message=".*No runtime found.*")
|
|
19
|
-
warnings.filterwarnings("ignore", message=".*Session state does not function.*")
|
|
20
|
-
warnings.filterwarnings("ignore", message=".*to view this Streamlit app.*")
|
|
15
|
+
# Suppress warnings before other imports
|
|
16
|
+
from mcli.ml.dashboard.common import suppress_streamlit_warnings
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
warnings.filterwarnings("ignore", message=".*keyword arguments have been deprecated.*")
|
|
24
|
-
warnings.filterwarnings("ignore", message=".*Use `config` instead.*")
|
|
25
|
-
|
|
26
|
-
# Suppress media file errors
|
|
27
|
-
warnings.filterwarnings("ignore", message=".*MediaFileHandler.*")
|
|
28
|
-
warnings.filterwarnings("ignore", message=".*Missing file.*")
|
|
29
|
-
warnings.filterwarnings("ignore", message=".*Bad filename.*")
|
|
30
|
-
|
|
31
|
-
# Suppress additional warnings
|
|
32
|
-
warnings.filterwarnings("ignore", category=UserWarning)
|
|
33
|
-
warnings.filterwarnings("ignore", category=FutureWarning)
|
|
18
|
+
suppress_streamlit_warnings()
|
|
34
19
|
|
|
35
20
|
logger = logging.getLogger(__name__)
|
|
36
21
|
|
|
37
|
-
# Suppress specific Streamlit media file errors in logging
|
|
38
|
-
logging.getLogger("streamlit.runtime.media_file_storage").setLevel(logging.ERROR)
|
|
39
|
-
logging.getLogger("streamlit.web.server.media_file_handler").setLevel(logging.ERROR)
|
|
40
22
|
import pandas as pd
|
|
41
23
|
import plotly.express as px
|
|
42
24
|
import plotly.graph_objects as go
|
|
43
25
|
import requests
|
|
44
26
|
import streamlit as st
|
|
45
|
-
from dotenv import load_dotenv
|
|
46
27
|
from plotly.subplots import make_subplots
|
|
47
|
-
from supabase import Client
|
|
28
|
+
from supabase import Client
|
|
29
|
+
|
|
30
|
+
# Import common dashboard utilities
|
|
31
|
+
from mcli.ml.dashboard.common import (
|
|
32
|
+
get_supabase_client,
|
|
33
|
+
load_environment_variables,
|
|
34
|
+
setup_page_config,
|
|
35
|
+
)
|
|
36
|
+
from mcli.ml.dashboard.styles import apply_dashboard_styles
|
|
48
37
|
|
|
49
|
-
# Load environment variables
|
|
50
|
-
|
|
38
|
+
# Load environment variables
|
|
39
|
+
load_environment_variables()
|
|
51
40
|
|
|
52
41
|
# Import streamlit-extras utilities
|
|
53
42
|
try:
|
|
@@ -111,7 +100,7 @@ show_debug_dependencies = None
|
|
|
111
100
|
|
|
112
101
|
# Import Overview page
|
|
113
102
|
try:
|
|
114
|
-
from mcli.ml.dashboard.
|
|
103
|
+
from mcli.ml.dashboard.overview import show_overview
|
|
115
104
|
HAS_OVERVIEW_PAGE = True
|
|
116
105
|
except (ImportError, KeyError, ModuleNotFoundError) as e:
|
|
117
106
|
st.warning(f"Overview page not available: {e}")
|
|
@@ -217,24 +206,19 @@ try:
|
|
|
217
206
|
except (ImportError, KeyError, ModuleNotFoundError) as e:
|
|
218
207
|
st.warning(f"Debug Dependencies page not available: {e}")
|
|
219
208
|
|
|
220
|
-
# Page config
|
|
221
|
-
|
|
209
|
+
# Page config - must be before other st commands
|
|
210
|
+
setup_page_config(
|
|
222
211
|
page_title="Politician Trading Tracker - MCLI",
|
|
223
|
-
page_icon="📊"
|
|
224
|
-
layout="wide",
|
|
225
|
-
initial_sidebar_state="expanded",
|
|
212
|
+
page_icon="📊"
|
|
226
213
|
)
|
|
227
214
|
|
|
228
|
-
#
|
|
215
|
+
# Apply standard dashboard styles (includes metric-card, alert boxes)
|
|
216
|
+
apply_dashboard_styles()
|
|
217
|
+
|
|
218
|
+
# Add integrated dashboard-specific CSS
|
|
229
219
|
st.markdown(
|
|
230
220
|
"""
|
|
231
221
|
<style>
|
|
232
|
-
.metric-card {
|
|
233
|
-
background-color: #f0f2f6;
|
|
234
|
-
padding: 1rem;
|
|
235
|
-
border-radius: 0.5rem;
|
|
236
|
-
border-left: 4px solid #1f77b4;
|
|
237
|
-
}
|
|
238
222
|
.success-box {
|
|
239
223
|
background-color: #d4edda;
|
|
240
224
|
border: 1px solid #c3e6cb;
|
|
@@ -254,69 +238,7 @@ st.markdown(
|
|
|
254
238
|
unsafe_allow_html=True,
|
|
255
239
|
)
|
|
256
240
|
|
|
257
|
-
|
|
258
|
-
@st.cache_resource
|
|
259
|
-
def get_supabase_client() -> Client:
|
|
260
|
-
"""Get Supabase client with Streamlit Cloud secrets support"""
|
|
261
|
-
# Try Streamlit secrets first (for Streamlit Cloud), then fall back to environment variables (for local dev)
|
|
262
|
-
try:
|
|
263
|
-
url = st.secrets.get("SUPABASE_URL", "")
|
|
264
|
-
key = st.secrets.get("SUPABASE_KEY", "") or st.secrets.get("SUPABASE_SERVICE_ROLE_KEY", "")
|
|
265
|
-
except (AttributeError, FileNotFoundError):
|
|
266
|
-
# Secrets not available, try environment variables
|
|
267
|
-
url = os.getenv("SUPABASE_URL", "")
|
|
268
|
-
key = os.getenv("SUPABASE_KEY", "") or os.getenv("SUPABASE_SERVICE_ROLE_KEY", "")
|
|
269
|
-
|
|
270
|
-
if not url or not key:
|
|
271
|
-
st.error(
|
|
272
|
-
"❌ Supabase credentials not configured"
|
|
273
|
-
)
|
|
274
|
-
with st.expander("🔧 Configuration Required"):
|
|
275
|
-
st.markdown("""
|
|
276
|
-
**Missing Supabase credentials:**
|
|
277
|
-
- `SUPABASE_URL`: {}
|
|
278
|
-
- `SUPABASE_KEY`: {}
|
|
279
|
-
|
|
280
|
-
**For Streamlit Cloud:**
|
|
281
|
-
1. Go to https://share.streamlit.io
|
|
282
|
-
2. Select your app → Settings → Secrets
|
|
283
|
-
3. Add:
|
|
284
|
-
```toml
|
|
285
|
-
SUPABASE_URL = "https://your-project.supabase.co"
|
|
286
|
-
SUPABASE_KEY = "your-anon-key"
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
**For local development:**
|
|
290
|
-
1. Create `.streamlit/secrets.toml` file
|
|
291
|
-
2. Add the same credentials as above
|
|
292
|
-
3. Restart the dashboard
|
|
293
|
-
|
|
294
|
-
**Using demo data** until configured.
|
|
295
|
-
""".format(
|
|
296
|
-
"✅ Set" if url else "❌ Missing",
|
|
297
|
-
"✅ Set" if key else "❌ Missing"
|
|
298
|
-
))
|
|
299
|
-
return None
|
|
300
|
-
|
|
301
|
-
try:
|
|
302
|
-
client = create_client(url, key)
|
|
303
|
-
# Test connection with a simple query
|
|
304
|
-
try:
|
|
305
|
-
test_result = client.table("politicians").select("id").limit(1).execute()
|
|
306
|
-
logger.info(f"✅ Supabase connection successful (URL: {url[:30]}...)")
|
|
307
|
-
return client
|
|
308
|
-
except Exception as conn_error:
|
|
309
|
-
st.error(f"❌ Supabase connection failed: {conn_error}")
|
|
310
|
-
with st.expander("🔍 Connection Details"):
|
|
311
|
-
st.write(f"**URL:** {url[:30]}...")
|
|
312
|
-
st.write(f"**Error:** {str(conn_error)}")
|
|
313
|
-
st.write("**Using demo data** until connection is restored.")
|
|
314
|
-
logger.error(f"Supabase connection test failed: {conn_error}")
|
|
315
|
-
return None
|
|
316
|
-
except Exception as e:
|
|
317
|
-
st.error(f"❌ Failed to create Supabase client: {e}")
|
|
318
|
-
logger.error(f"Failed to create Supabase client: {e}")
|
|
319
|
-
return None
|
|
241
|
+
# Note: get_supabase_client is now imported from common.py
|
|
320
242
|
|
|
321
243
|
|
|
322
244
|
@st.cache_data(ttl=300) # Cache for 5 minutes
|
|
@@ -1,75 +1,26 @@
|
|
|
1
1
|
"""Streamlit dashboard for ML system monitoring - Supabase version"""
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
-
import os
|
|
5
4
|
from datetime import datetime, timedelta
|
|
6
|
-
from pathlib import Path
|
|
7
5
|
|
|
8
6
|
import numpy as np
|
|
9
7
|
import pandas as pd
|
|
10
8
|
import plotly.express as px
|
|
11
9
|
import plotly.graph_objects as go
|
|
12
10
|
import streamlit as st
|
|
13
|
-
from dotenv import load_dotenv
|
|
14
11
|
from plotly.subplots import make_subplots
|
|
15
|
-
|
|
12
|
+
|
|
13
|
+
from mcli.ml.dashboard.common import get_supabase_client, load_environment_variables, setup_page_config
|
|
14
|
+
from mcli.ml.dashboard.styles import apply_dashboard_styles
|
|
16
15
|
|
|
17
16
|
# Page config must come first
|
|
18
|
-
|
|
19
|
-
page_title="MCLI ML Dashboard", page_icon="📊", layout="wide", initial_sidebar_state="expanded"
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
# Load environment variables from supabase/.env.local
|
|
23
|
-
env_path = Path(__file__).parent.parent.parent.parent.parent / "supabase" / ".env.local"
|
|
24
|
-
if env_path.exists():
|
|
25
|
-
load_dotenv(env_path)
|
|
26
|
-
|
|
27
|
-
# Custom CSS
|
|
28
|
-
st.markdown(
|
|
29
|
-
"""
|
|
30
|
-
<style>
|
|
31
|
-
.metric-card {
|
|
32
|
-
background-color: #f0f2f6;
|
|
33
|
-
padding: 1rem;
|
|
34
|
-
border-radius: 0.5rem;
|
|
35
|
-
border-left: 4px solid #1f77b4;
|
|
36
|
-
}
|
|
37
|
-
</style>
|
|
38
|
-
""",
|
|
39
|
-
unsafe_allow_html=True,
|
|
40
|
-
)
|
|
17
|
+
setup_page_config(page_title="MCLI ML Dashboard")
|
|
41
18
|
|
|
19
|
+
# Load environment variables
|
|
20
|
+
load_environment_variables()
|
|
42
21
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"""Get Supabase client with Streamlit Cloud secrets support"""
|
|
46
|
-
# Try Streamlit secrets first (for Streamlit Cloud), then fall back to environment variables (for local dev)
|
|
47
|
-
try:
|
|
48
|
-
url = st.secrets.get("SUPABASE_URL", "")
|
|
49
|
-
key = st.secrets.get("SUPABASE_KEY", "") or st.secrets.get("SUPABASE_SERVICE_ROLE_KEY", "")
|
|
50
|
-
except (AttributeError, FileNotFoundError):
|
|
51
|
-
# Secrets not available, try environment variables
|
|
52
|
-
url = os.getenv("SUPABASE_URL", "")
|
|
53
|
-
key = os.getenv("SUPABASE_KEY", "") or os.getenv("SUPABASE_SERVICE_ROLE_KEY", "")
|
|
54
|
-
|
|
55
|
-
if not url or not key:
|
|
56
|
-
st.warning(
|
|
57
|
-
"⚠️ Supabase credentials not found. Configure SUPABASE_URL and SUPABASE_KEY in Streamlit Cloud secrets or environment variables."
|
|
58
|
-
)
|
|
59
|
-
return None
|
|
60
|
-
|
|
61
|
-
try:
|
|
62
|
-
client = create_client(url, key)
|
|
63
|
-
# Test connection
|
|
64
|
-
try:
|
|
65
|
-
client.table("politicians").select("id").limit(1).execute()
|
|
66
|
-
return client
|
|
67
|
-
except Exception as e:
|
|
68
|
-
st.error(f"❌ Supabase connection test failed: {e}")
|
|
69
|
-
return None
|
|
70
|
-
except Exception as e:
|
|
71
|
-
st.error(f"❌ Failed to create Supabase client: {e}")
|
|
72
|
-
return None
|
|
22
|
+
# Apply standard dashboard styles
|
|
23
|
+
apply_dashboard_styles()
|
|
73
24
|
|
|
74
25
|
|
|
75
26
|
@st.cache_data(ttl=30)
|