mcli-framework 7.3.1__py3-none-any.whl → 7.4.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/commands_cmd.py +741 -0
- mcli/ml/dashboard/app_integrated.py +286 -37
- mcli/ml/dashboard/app_training.py +1 -1
- mcli/ml/dashboard/pages/cicd.py +1 -1
- mcli/ml/dashboard/pages/debug_dependencies.py +364 -0
- mcli/ml/dashboard/pages/gravity_viz.py +565 -0
- mcli/ml/dashboard/pages/monte_carlo_predictions.py +555 -0
- mcli/ml/dashboard/pages/overview.py +378 -0
- mcli/ml/dashboard/pages/scrapers_and_logs.py +22 -6
- mcli/ml/dashboard/pages/test_portfolio.py +54 -4
- mcli/ml/dashboard/pages/trading.py +80 -26
- mcli/ml/dashboard/streamlit_extras_utils.py +297 -0
- mcli/ml/dashboard/utils.py +7 -0
- mcli/ml/dashboard/warning_suppression.py +34 -0
- mcli/ml/database/session.py +169 -16
- mcli/ml/predictions/monte_carlo.py +428 -0
- mcli/ml/trading/__init__.py +7 -1
- mcli/ml/trading/alpaca_client.py +82 -18
- mcli/self/self_cmd.py +263 -24
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.4.0.dist-info}/METADATA +3 -2
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.4.0.dist-info}/RECORD +25 -18
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.4.0.dist-info}/WHEEL +0 -0
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.4.0.dist-info}/entry_points.txt +0 -0
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.4.0.dist-info}/licenses/LICENSE +0 -0
- {mcli_framework-7.3.1.dist-info → mcli_framework-7.4.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Trading dashboard page for portfolio management and trade execution"""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import warnings
|
|
4
5
|
from datetime import datetime, timedelta
|
|
5
6
|
from typing import Dict, List, Optional
|
|
6
7
|
from uuid import UUID
|
|
@@ -11,6 +12,12 @@ import plotly.graph_objects as go
|
|
|
11
12
|
from plotly.subplots import make_subplots
|
|
12
13
|
import streamlit as st
|
|
13
14
|
|
|
15
|
+
# Suppress Streamlit warnings when used outside runtime context
|
|
16
|
+
warnings.filterwarnings("ignore", message=".*missing ScriptRunContext.*")
|
|
17
|
+
warnings.filterwarnings("ignore", message=".*No runtime found.*")
|
|
18
|
+
warnings.filterwarnings("ignore", message=".*Session state does not function.*")
|
|
19
|
+
warnings.filterwarnings("ignore", message=".*to view this Streamlit app.*")
|
|
20
|
+
|
|
14
21
|
# Try to import trading dependencies with fallbacks
|
|
15
22
|
try:
|
|
16
23
|
from sqlalchemy.orm import Session
|
|
@@ -64,6 +71,9 @@ def show_trading_dashboard():
|
|
|
64
71
|
"""Main trading dashboard page"""
|
|
65
72
|
st.title("📈 Trading Dashboard")
|
|
66
73
|
st.markdown("Manage your portfolios and execute trades based on politician trading insights")
|
|
74
|
+
|
|
75
|
+
# Add a simple test to ensure the page is rendering
|
|
76
|
+
st.info("📋 Page loaded successfully - Trading Dashboard functionality is available")
|
|
67
77
|
|
|
68
78
|
# Check if trading dependencies are available
|
|
69
79
|
if not HAS_TRADING_DEPS:
|
|
@@ -215,7 +225,7 @@ def show_trading_overview():
|
|
|
215
225
|
labels={"total_return_pct": "Total Return (%)", "date": "Date"}
|
|
216
226
|
)
|
|
217
227
|
fig.update_layout(height=400)
|
|
218
|
-
st.plotly_chart(fig, use_container_width=True)
|
|
228
|
+
st.plotly_chart(fig, config={"displayModeBar": True}, use_container_width=True)
|
|
219
229
|
else:
|
|
220
230
|
st.info("No performance data available yet. Start trading to see your performance!")
|
|
221
231
|
|
|
@@ -570,7 +580,7 @@ def show_performance_page():
|
|
|
570
580
|
fig.update_yaxes(title_text="Portfolio Value ($)", row=1, col=1)
|
|
571
581
|
fig.update_yaxes(title_text="Daily Return (%)", row=2, col=1)
|
|
572
582
|
|
|
573
|
-
st.plotly_chart(fig, use_container_width=True)
|
|
583
|
+
st.plotly_chart(fig, config={"displayModeBar": True}, use_container_width=True)
|
|
574
584
|
else:
|
|
575
585
|
st.info("No performance data available yet")
|
|
576
586
|
|
|
@@ -667,38 +677,77 @@ def show_signals_page():
|
|
|
667
677
|
|
|
668
678
|
def show_settings_page():
|
|
669
679
|
"""Show trading settings page"""
|
|
680
|
+
import os
|
|
681
|
+
|
|
670
682
|
st.header("⚙️ Trading Settings")
|
|
671
|
-
|
|
683
|
+
|
|
672
684
|
st.subheader("Alpaca API Configuration")
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
685
|
+
|
|
686
|
+
# Check current configuration from environment
|
|
687
|
+
api_key_configured = bool(os.getenv("ALPACA_API_KEY"))
|
|
688
|
+
secret_key_configured = bool(os.getenv("ALPACA_SECRET_KEY"))
|
|
689
|
+
base_url = os.getenv("ALPACA_BASE_URL", "https://paper-api.alpaca.markets")
|
|
690
|
+
is_paper = "paper" in base_url.lower()
|
|
691
|
+
|
|
692
|
+
# Show current configuration status
|
|
693
|
+
st.info("📝 **Configuration Status**")
|
|
694
|
+
col1, col2, col3 = st.columns(3)
|
|
695
|
+
|
|
696
|
+
with col1:
|
|
697
|
+
if api_key_configured:
|
|
698
|
+
st.success("✅ API Key Configured")
|
|
699
|
+
# Show masked version
|
|
700
|
+
api_key_value = os.getenv("ALPACA_API_KEY", "")
|
|
701
|
+
if len(api_key_value) > 8:
|
|
702
|
+
masked_key = api_key_value[:4] + "..." + api_key_value[-4:]
|
|
703
|
+
st.code(masked_key)
|
|
704
|
+
else:
|
|
705
|
+
st.error("❌ API Key Not Set")
|
|
706
|
+
|
|
707
|
+
with col2:
|
|
708
|
+
if secret_key_configured:
|
|
709
|
+
st.success("✅ Secret Key Configured")
|
|
710
|
+
else:
|
|
711
|
+
st.error("❌ Secret Key Not Set")
|
|
712
|
+
|
|
713
|
+
with col3:
|
|
714
|
+
st.metric("Environment", "Paper Trading" if is_paper else "Live Trading")
|
|
715
|
+
|
|
716
|
+
st.markdown("---")
|
|
717
|
+
|
|
718
|
+
# Configuration instructions
|
|
719
|
+
with st.expander("🔧 How to Configure Alpaca API Keys"):
|
|
720
|
+
st.markdown("""
|
|
721
|
+
### Setting up Alpaca API Credentials
|
|
722
|
+
|
|
723
|
+
1. **Get your API keys from Alpaca:**
|
|
724
|
+
- Visit [Alpaca Dashboard](https://app.alpaca.markets/paper/dashboard/overview)
|
|
725
|
+
- Go to "Your API Keys" section
|
|
726
|
+
- Generate new API keys if needed
|
|
727
|
+
|
|
728
|
+
2. **Add keys to your `.env` file:**
|
|
729
|
+
```bash
|
|
730
|
+
ALPACA_API_KEY=your_api_key_here
|
|
731
|
+
ALPACA_SECRET_KEY=your_secret_key_here
|
|
732
|
+
ALPACA_BASE_URL=https://paper-api.alpaca.markets # For paper trading
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
3. **Restart the Streamlit app** to load the new configuration
|
|
736
|
+
|
|
737
|
+
**Current Configuration File:** `/Users/lefv/repos/mcli/.env`
|
|
738
|
+
""")
|
|
739
|
+
|
|
691
740
|
st.subheader("Risk Management")
|
|
692
|
-
|
|
741
|
+
|
|
693
742
|
col1, col2 = st.columns(2)
|
|
694
|
-
|
|
743
|
+
|
|
695
744
|
with col1:
|
|
696
745
|
st.metric("Current Max Position Size", "10%")
|
|
697
746
|
st.metric("Current Max Portfolio Risk", "20%")
|
|
698
|
-
|
|
747
|
+
|
|
699
748
|
with col2:
|
|
700
749
|
st.metric("Active Risk Level", "Moderate")
|
|
701
|
-
st.metric("Paper Trading", "Enabled")
|
|
750
|
+
st.metric("Paper Trading", "Enabled" if is_paper else "Disabled")
|
|
702
751
|
|
|
703
752
|
st.subheader("Portfolio Alerts")
|
|
704
753
|
|
|
@@ -711,4 +760,9 @@ def show_settings_page():
|
|
|
711
760
|
]
|
|
712
761
|
|
|
713
762
|
for alert_type in alert_types:
|
|
714
|
-
st.checkbox(alert_type, value=True)
|
|
763
|
+
st.checkbox(alert_type, value=True)
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
# Module-level execution only when run directly (not when imported)
|
|
767
|
+
if __name__ == "__main__":
|
|
768
|
+
show_trading_dashboard()
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"""Utility functions using streamlit-extras for enhanced dashboard UI"""
|
|
2
|
+
|
|
3
|
+
import streamlit as st
|
|
4
|
+
|
|
5
|
+
# Try to import streamlit-extras components
|
|
6
|
+
HAS_EXTRAS = True
|
|
7
|
+
try:
|
|
8
|
+
from streamlit_extras.metric_cards import style_metric_cards
|
|
9
|
+
from streamlit_extras.badges import badge
|
|
10
|
+
from streamlit_extras.colored_header import colored_header
|
|
11
|
+
from streamlit_extras.card import card
|
|
12
|
+
from streamlit_extras.stoggle import stoggle
|
|
13
|
+
from streamlit_extras.grid import grid
|
|
14
|
+
from streamlit_extras.add_vertical_space import add_vertical_space
|
|
15
|
+
from streamlit_extras.stylable_container import stylable_container
|
|
16
|
+
except ImportError:
|
|
17
|
+
HAS_EXTRAS = False
|
|
18
|
+
style_metric_cards = None
|
|
19
|
+
badge = None
|
|
20
|
+
colored_header = None
|
|
21
|
+
card = None
|
|
22
|
+
stoggle = None
|
|
23
|
+
grid = None
|
|
24
|
+
add_vertical_space = None
|
|
25
|
+
stylable_container = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def enhanced_metrics(metrics_data: list, use_container_width: bool = True):
|
|
29
|
+
"""
|
|
30
|
+
Display enhanced metric cards with styling from streamlit-extras
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
metrics_data: List of dicts with keys: label, value, delta (optional)
|
|
34
|
+
use_container_width: Whether to use full container width
|
|
35
|
+
|
|
36
|
+
Example:
|
|
37
|
+
enhanced_metrics([
|
|
38
|
+
{"label": "Total Transactions", "value": "1,234", "delta": "+12%"},
|
|
39
|
+
{"label": "Portfolio Value", "value": "$50,000", "delta": "-2.3%"},
|
|
40
|
+
])
|
|
41
|
+
"""
|
|
42
|
+
if not HAS_EXTRAS:
|
|
43
|
+
# Fallback to standard metrics
|
|
44
|
+
cols = st.columns(len(metrics_data))
|
|
45
|
+
for i, metric in enumerate(metrics_data):
|
|
46
|
+
with cols[i]:
|
|
47
|
+
st.metric(
|
|
48
|
+
label=metric["label"],
|
|
49
|
+
value=metric["value"],
|
|
50
|
+
delta=metric.get("delta")
|
|
51
|
+
)
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
# Use streamlit-extras styled metrics
|
|
55
|
+
cols = st.columns(len(metrics_data))
|
|
56
|
+
for i, metric in enumerate(metrics_data):
|
|
57
|
+
with cols[i]:
|
|
58
|
+
st.metric(
|
|
59
|
+
label=metric["label"],
|
|
60
|
+
value=metric["value"],
|
|
61
|
+
delta=metric.get("delta")
|
|
62
|
+
)
|
|
63
|
+
style_metric_cards()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def status_badge(label: str, url: str = None):
|
|
67
|
+
"""
|
|
68
|
+
Display a status badge
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
label: Badge text (e.g., "Live", "Production", "Beta")
|
|
72
|
+
url: Optional URL to link to
|
|
73
|
+
"""
|
|
74
|
+
if not HAS_EXTRAS:
|
|
75
|
+
st.markdown(f"**{label}**")
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
badge(type="success", name=label, url=url)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def section_header(label: str, description: str = None, divider: str = "rainbow"):
|
|
82
|
+
"""
|
|
83
|
+
Display a colored section header with optional description
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
label: Header text
|
|
87
|
+
description: Optional description text
|
|
88
|
+
divider: Color of divider line
|
|
89
|
+
"""
|
|
90
|
+
if not HAS_EXTRAS:
|
|
91
|
+
st.header(label)
|
|
92
|
+
if description:
|
|
93
|
+
st.markdown(description)
|
|
94
|
+
st.divider()
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
colored_header(
|
|
98
|
+
label=label,
|
|
99
|
+
description=description or "",
|
|
100
|
+
color_name=divider
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def info_card(title: str, text: str, image: str = None, url: str = None,
|
|
105
|
+
has_button: bool = False, button_text: str = "Learn More"):
|
|
106
|
+
"""
|
|
107
|
+
Display an information card
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
title: Card title
|
|
111
|
+
text: Card content
|
|
112
|
+
image: Optional image URL
|
|
113
|
+
url: Optional URL to link to
|
|
114
|
+
has_button: Whether to show a button
|
|
115
|
+
button_text: Button text if has_button is True
|
|
116
|
+
"""
|
|
117
|
+
if not HAS_EXTRAS:
|
|
118
|
+
with st.container():
|
|
119
|
+
st.subheader(title)
|
|
120
|
+
if image:
|
|
121
|
+
st.image(image)
|
|
122
|
+
st.markdown(text)
|
|
123
|
+
if url and has_button:
|
|
124
|
+
st.link_button(button_text, url)
|
|
125
|
+
return
|
|
126
|
+
|
|
127
|
+
kwargs = {
|
|
128
|
+
"title": title,
|
|
129
|
+
"text": text,
|
|
130
|
+
}
|
|
131
|
+
if image:
|
|
132
|
+
kwargs["image"] = image
|
|
133
|
+
if url:
|
|
134
|
+
kwargs["url"] = url
|
|
135
|
+
|
|
136
|
+
card(**kwargs)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def collapsible_section(label: str, content_fn, default_open: bool = False):
|
|
140
|
+
"""
|
|
141
|
+
Create a collapsible toggle section
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
label: Section label
|
|
145
|
+
content_fn: Function to call to render content
|
|
146
|
+
default_open: Whether section starts open
|
|
147
|
+
"""
|
|
148
|
+
if not HAS_EXTRAS:
|
|
149
|
+
with st.expander(label, expanded=default_open):
|
|
150
|
+
content_fn()
|
|
151
|
+
return
|
|
152
|
+
|
|
153
|
+
stoggle(label, content_fn)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def dashboard_grid(num_cols: int = 3, gap: str = "medium"):
|
|
157
|
+
"""
|
|
158
|
+
Create a responsive grid layout
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
num_cols: Number of columns
|
|
162
|
+
gap: Gap size between columns
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Grid object for use in with statement
|
|
166
|
+
"""
|
|
167
|
+
if not HAS_EXTRAS:
|
|
168
|
+
return st.columns(num_cols)
|
|
169
|
+
|
|
170
|
+
return grid(num_cols, gap=gap)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def vertical_space(lines: int = 1):
|
|
174
|
+
"""
|
|
175
|
+
Add vertical spacing
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
lines: Number of lines to add
|
|
179
|
+
"""
|
|
180
|
+
if not HAS_EXTRAS:
|
|
181
|
+
for _ in range(lines):
|
|
182
|
+
st.write("")
|
|
183
|
+
return
|
|
184
|
+
|
|
185
|
+
add_vertical_space(lines)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def styled_container(key: str, css_styles: str):
|
|
189
|
+
"""
|
|
190
|
+
Create a container with custom CSS styling
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
key: Unique key for the container
|
|
194
|
+
css_styles: CSS styles to apply
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Context manager for styled container
|
|
198
|
+
"""
|
|
199
|
+
if not HAS_EXTRAS:
|
|
200
|
+
return st.container()
|
|
201
|
+
|
|
202
|
+
return stylable_container(
|
|
203
|
+
key=key,
|
|
204
|
+
css_styles=css_styles
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def trading_status_card(status: str, portfolio_value: float, daily_pnl: float,
|
|
209
|
+
positions: int, cash: float):
|
|
210
|
+
"""
|
|
211
|
+
Display a trading status summary card
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
status: Trading status (e.g., "Active", "Paused")
|
|
215
|
+
portfolio_value: Current portfolio value
|
|
216
|
+
daily_pnl: Daily profit/loss
|
|
217
|
+
positions: Number of open positions
|
|
218
|
+
cash: Available cash
|
|
219
|
+
"""
|
|
220
|
+
status_color = "🟢" if status == "Active" else "🔴"
|
|
221
|
+
pnl_emoji = "📈" if daily_pnl >= 0 else "📉"
|
|
222
|
+
pnl_sign = "+" if daily_pnl >= 0 else ""
|
|
223
|
+
|
|
224
|
+
section_header(
|
|
225
|
+
f"{status_color} Trading Status: {status}",
|
|
226
|
+
f"Real-time portfolio monitoring and execution",
|
|
227
|
+
divider="blue"
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
enhanced_metrics([
|
|
231
|
+
{
|
|
232
|
+
"label": "Portfolio Value",
|
|
233
|
+
"value": f"${portfolio_value:,.2f}",
|
|
234
|
+
"delta": f"{pnl_sign}${daily_pnl:,.2f}"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"label": "Open Positions",
|
|
238
|
+
"value": str(positions),
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"label": "Available Cash",
|
|
242
|
+
"value": f"${cash:,.2f}",
|
|
243
|
+
},
|
|
244
|
+
])
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def data_quality_indicators(total_records: int, clean_records: int,
|
|
248
|
+
errors: int, last_update: str):
|
|
249
|
+
"""
|
|
250
|
+
Display data quality indicators
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
total_records: Total number of records
|
|
254
|
+
clean_records: Number of clean records
|
|
255
|
+
errors: Number of errors
|
|
256
|
+
last_update: Last update timestamp
|
|
257
|
+
"""
|
|
258
|
+
quality_pct = (clean_records / total_records * 100) if total_records > 0 else 0
|
|
259
|
+
|
|
260
|
+
section_header(
|
|
261
|
+
"📊 Data Quality Metrics",
|
|
262
|
+
f"Last updated: {last_update}",
|
|
263
|
+
divider="green"
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
enhanced_metrics([
|
|
267
|
+
{
|
|
268
|
+
"label": "Total Records",
|
|
269
|
+
"value": f"{total_records:,}",
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"label": "Data Quality",
|
|
273
|
+
"value": f"{quality_pct:.1f}%",
|
|
274
|
+
"delta": f"{clean_records:,} clean"
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"label": "Errors",
|
|
278
|
+
"value": str(errors),
|
|
279
|
+
"delta": f"{(errors/total_records*100):.2f}%" if total_records > 0 else "0%"
|
|
280
|
+
},
|
|
281
|
+
])
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
# Export available components
|
|
285
|
+
__all__ = [
|
|
286
|
+
'HAS_EXTRAS',
|
|
287
|
+
'enhanced_metrics',
|
|
288
|
+
'status_badge',
|
|
289
|
+
'section_header',
|
|
290
|
+
'info_card',
|
|
291
|
+
'collapsible_section',
|
|
292
|
+
'dashboard_grid',
|
|
293
|
+
'vertical_space',
|
|
294
|
+
'styled_container',
|
|
295
|
+
'trading_status_card',
|
|
296
|
+
'data_quality_indicators',
|
|
297
|
+
]
|
mcli/ml/dashboard/utils.py
CHANGED
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import logging
|
|
5
|
+
import warnings
|
|
5
6
|
from typing import List, Optional
|
|
6
7
|
import pandas as pd
|
|
7
8
|
import streamlit as st
|
|
8
9
|
from supabase import Client, create_client
|
|
9
10
|
|
|
11
|
+
# Suppress Streamlit warnings when used outside runtime context
|
|
12
|
+
warnings.filterwarnings("ignore", message=".*missing ScriptRunContext.*")
|
|
13
|
+
warnings.filterwarnings("ignore", message=".*No runtime found.*")
|
|
14
|
+
warnings.filterwarnings("ignore", message=".*Session state does not function.*")
|
|
15
|
+
warnings.filterwarnings("ignore", message=".*to view this Streamlit app.*")
|
|
16
|
+
|
|
10
17
|
logger = logging.getLogger(__name__)
|
|
11
18
|
|
|
12
19
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Warning suppression utilities for Streamlit components used outside runtime context"""
|
|
2
|
+
|
|
3
|
+
import warnings
|
|
4
|
+
import logging
|
|
5
|
+
from contextlib import contextmanager
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@contextmanager
|
|
9
|
+
def suppress_streamlit_warnings():
|
|
10
|
+
"""Context manager to suppress Streamlit warnings when used outside runtime context"""
|
|
11
|
+
# Suppress specific Streamlit warnings
|
|
12
|
+
with warnings.catch_warnings():
|
|
13
|
+
warnings.filterwarnings("ignore", message=".*missing ScriptRunContext.*")
|
|
14
|
+
warnings.filterwarnings("ignore", message=".*No runtime found.*")
|
|
15
|
+
warnings.filterwarnings("ignore", message=".*Session state does not function.*")
|
|
16
|
+
warnings.filterwarnings("ignore", message=".*to view this Streamlit app.*")
|
|
17
|
+
|
|
18
|
+
# Also suppress logging warnings from Streamlit
|
|
19
|
+
streamlit_logger = logging.getLogger("streamlit")
|
|
20
|
+
original_level = streamlit_logger.level
|
|
21
|
+
streamlit_logger.setLevel(logging.ERROR)
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
yield
|
|
25
|
+
finally:
|
|
26
|
+
streamlit_logger.setLevel(original_level)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def suppress_streamlit_warnings_decorator(func):
|
|
30
|
+
"""Decorator to suppress Streamlit warnings for a function"""
|
|
31
|
+
def wrapper(*args, **kwargs):
|
|
32
|
+
with suppress_streamlit_warnings():
|
|
33
|
+
return func(*args, **kwargs)
|
|
34
|
+
return wrapper
|