Spaces:
Runtime error
Runtime error
Simplify Gradio interface to debug TypeError
Browse files
app.py
CHANGED
|
@@ -28,24 +28,28 @@ except ImportError as e:
|
|
| 28 |
|
| 29 |
|
| 30 |
# --- Data Fetching and Processing Logic ---
|
| 31 |
-
|
| 32 |
-
# Added a comment below to trigger rebuild
|
| 33 |
-
def perform_analysis(ticker_symbol, start_date_str, end_date_str): # Renamed date inputs
|
| 34 |
"""Fetches data, analyzes sentiment, merges, and prepares outputs for Gradio."""
|
| 35 |
if not ticker_symbol:
|
| 36 |
-
|
|
|
|
| 37 |
|
| 38 |
# Ensure API keys are loaded (needed for news)
|
| 39 |
news_key, _ = load_api_keys()
|
| 40 |
if not news_key:
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
status_updates = f"Fetching data for {ticker_symbol} from {start_date_str} to {end_date_str}...\n"
|
| 51 |
|
|
@@ -53,13 +57,12 @@ def perform_analysis(ticker_symbol, start_date_str, end_date_str): # Renamed dat
|
|
| 53 |
stock_df = get_stock_data(ticker_symbol, start_date_str, end_date_str)
|
| 54 |
if stock_df is None or stock_df.empty:
|
| 55 |
status_updates += "Could not fetch stock data.\n"
|
| 56 |
-
# Return early if essential data is missing
|
| 57 |
-
return None, status_updates, None,
|
| 58 |
else:
|
| 59 |
status_updates += f"Successfully fetched {len(stock_df)} days of stock data.\n"
|
| 60 |
stock_df['Date'] = pd.to_datetime(stock_df['Date'])
|
| 61 |
|
| 62 |
-
|
| 63 |
# 2. Fetch News Articles
|
| 64 |
articles_list = get_news_articles(ticker_symbol, start_date_str, end_date_str)
|
| 65 |
if articles_list is None or not articles_list:
|
|
@@ -198,7 +201,8 @@ def perform_analysis(ticker_symbol, start_date_str, end_date_str): # Renamed dat
|
|
| 198 |
status_updates += "Prepared recent news table.\n"
|
| 199 |
|
| 200 |
|
| 201 |
-
|
|
|
|
| 202 |
|
| 203 |
|
| 204 |
# --- Gradio Interface Definition ---
|
|
@@ -208,48 +212,43 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 208 |
with gr.Row():
|
| 209 |
with gr.Column(scale=1):
|
| 210 |
ticker_input = gr.Textbox(label="Stock Ticker", value="AAPL", placeholder="e.g., AAPL, GOOGL")
|
| 211 |
-
# Use Textbox for dates, value should be string
|
| 212 |
start_date_input = gr.Textbox(label="Start Date (YYYY-MM-DD)", value=(datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d'))
|
| 213 |
end_date_input = gr.Textbox(label="End Date (YYYY-MM-DD)", value=datetime.now().strftime('%Y-%m-%d'))
|
| 214 |
analyze_button = gr.Button("Analyze", variant="primary")
|
| 215 |
status_output = gr.Textbox(label="Analysis Status", lines=5, interactive=False)
|
| 216 |
-
# Optional: Add download button for the merged data
|
| 217 |
-
download_data = gr.File(label="Download Merged Data (CSV)")
|
| 218 |
|
| 219 |
with gr.Column(scale=3):
|
| 220 |
plot_output = gr.Plot(label="Stock Price vs. Sentiment")
|
| 221 |
insights_output = gr.Markdown(label="Analysis & Insights")
|
| 222 |
news_output = gr.DataFrame(label="Recent News Headlines", headers=['Date', 'Title', 'Sentiment', 'Score'], wrap=True)
|
| 223 |
|
| 224 |
-
# Hidden state to store the merged dataframe for download
|
| 225 |
-
merged_df_state = gr.State(None)
|
| 226 |
|
| 227 |
# Modify the wrapper function to accept strings and parse them
|
| 228 |
def run_analysis_and_prepare_download(ticker, start_date_str, end_date_str):
|
| 229 |
-
"""Wrapper function to run analysis
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
return
|
| 237 |
-
|
| 238 |
-
#
|
| 239 |
-
plot, insights, news, status,
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
# Save to a temporary CSV file for Gradio download
|
| 244 |
-
csv_path = "temp_merged_data.csv"
|
| 245 |
-
merged_df.to_csv(csv_path, index=False)
|
| 246 |
-
|
| 247 |
-
return plot, insights, news, status, merged_df, csv_path # Return path for download
|
| 248 |
|
| 249 |
analyze_button.click(
|
| 250 |
fn=run_analysis_and_prepare_download,
|
| 251 |
inputs=[ticker_input, start_date_input, end_date_input], # Inputs are now textboxes
|
| 252 |
-
|
|
|
|
| 253 |
)
|
| 254 |
|
| 255 |
# --- Launch the App ---
|
|
|
|
| 28 |
|
| 29 |
|
| 30 |
# --- Data Fetching and Processing Logic ---
|
| 31 |
+
def perform_analysis(ticker_symbol, start_date_str, end_date_str):
|
|
|
|
|
|
|
| 32 |
"""Fetches data, analyzes sentiment, merges, and prepares outputs for Gradio."""
|
| 33 |
if not ticker_symbol:
|
| 34 |
+
# Return values match the simplified output count
|
| 35 |
+
return None, "Please enter a stock ticker.", None, "Input Error." # Plot, Insights, News, Status
|
| 36 |
|
| 37 |
# Ensure API keys are loaded (needed for news)
|
| 38 |
news_key, _ = load_api_keys()
|
| 39 |
if not news_key:
|
| 40 |
+
# Return values match the simplified output count
|
| 41 |
+
return None, "Error: NEWS_API_KEY not found in environment variables. Cannot fetch news.", None, "API Key Error." # Plot, Insights, News, Status
|
| 42 |
+
|
| 43 |
+
# Parse and validate dates inside perform_analysis
|
| 44 |
+
try:
|
| 45 |
+
start_date_obj = datetime.strptime(start_date_str, '%Y-%m-%d').date()
|
| 46 |
+
end_date_obj = datetime.strptime(end_date_str, '%Y-%m-%d').date()
|
| 47 |
+
if start_date_obj >= end_date_obj:
|
| 48 |
+
# Return values match the simplified output count
|
| 49 |
+
return None, "Error: Start date must be before end date.", None, "Date Error." # Plot, Insights, News, Status
|
| 50 |
+
except ValueError:
|
| 51 |
+
# Return values match the simplified output count
|
| 52 |
+
return None, "Error: Invalid date format. Please use YYYY-MM-DD.", None, "Date Format Error." # Plot, Insights, News, Status
|
| 53 |
|
| 54 |
status_updates = f"Fetching data for {ticker_symbol} from {start_date_str} to {end_date_str}...\n"
|
| 55 |
|
|
|
|
| 57 |
stock_df = get_stock_data(ticker_symbol, start_date_str, end_date_str)
|
| 58 |
if stock_df is None or stock_df.empty:
|
| 59 |
status_updates += "Could not fetch stock data.\n"
|
| 60 |
+
# Return early if essential data is missing (match simplified output count)
|
| 61 |
+
return None, status_updates, None, status_updates # Plot, Insights, News, Status
|
| 62 |
else:
|
| 63 |
status_updates += f"Successfully fetched {len(stock_df)} days of stock data.\n"
|
| 64 |
stock_df['Date'] = pd.to_datetime(stock_df['Date'])
|
| 65 |
|
|
|
|
| 66 |
# 2. Fetch News Articles
|
| 67 |
articles_list = get_news_articles(ticker_symbol, start_date_str, end_date_str)
|
| 68 |
if articles_list is None or not articles_list:
|
|
|
|
| 201 |
status_updates += "Prepared recent news table.\n"
|
| 202 |
|
| 203 |
|
| 204 |
+
# Final return includes merged_df for internal use, but wrapper selects outputs
|
| 205 |
+
return plot_object, insights_text, recent_news_df, status_updates, merged_df # Keep returning merged_df internally
|
| 206 |
|
| 207 |
|
| 208 |
# --- Gradio Interface Definition ---
|
|
|
|
| 212 |
with gr.Row():
|
| 213 |
with gr.Column(scale=1):
|
| 214 |
ticker_input = gr.Textbox(label="Stock Ticker", value="AAPL", placeholder="e.g., AAPL, GOOGL")
|
|
|
|
| 215 |
start_date_input = gr.Textbox(label="Start Date (YYYY-MM-DD)", value=(datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d'))
|
| 216 |
end_date_input = gr.Textbox(label="End Date (YYYY-MM-DD)", value=datetime.now().strftime('%Y-%m-%d'))
|
| 217 |
analyze_button = gr.Button("Analyze", variant="primary")
|
| 218 |
status_output = gr.Textbox(label="Analysis Status", lines=5, interactive=False)
|
| 219 |
+
# Optional: Add download button for the merged data - COMMENTED OUT
|
| 220 |
+
# download_data = gr.File(label="Download Merged Data (CSV)")
|
| 221 |
|
| 222 |
with gr.Column(scale=3):
|
| 223 |
plot_output = gr.Plot(label="Stock Price vs. Sentiment")
|
| 224 |
insights_output = gr.Markdown(label="Analysis & Insights")
|
| 225 |
news_output = gr.DataFrame(label="Recent News Headlines", headers=['Date', 'Title', 'Sentiment', 'Score'], wrap=True)
|
| 226 |
|
| 227 |
+
# Hidden state to store the merged dataframe for download - COMMENTED OUT
|
| 228 |
+
# merged_df_state = gr.State(None)
|
| 229 |
|
| 230 |
# Modify the wrapper function to accept strings and parse them
|
| 231 |
def run_analysis_and_prepare_download(ticker, start_date_str, end_date_str):
|
| 232 |
+
"""Wrapper function to run analysis."""
|
| 233 |
+
# Call perform_analysis which now handles date validation
|
| 234 |
+
# It returns 5 values: plot, insights, news, status, merged_df
|
| 235 |
+
results = perform_analysis(ticker, start_date_str, end_date_str)
|
| 236 |
+
|
| 237 |
+
# Check if perform_analysis returned an error tuple (4 elements)
|
| 238 |
+
if len(results) == 4:
|
| 239 |
+
return results[0], results[1], results[2], results[3] # plot, insights, news, status
|
| 240 |
+
|
| 241 |
+
# Otherwise, unpack the full 5 results
|
| 242 |
+
plot, insights, news, status, _ = results # Ignore merged_df for output
|
| 243 |
+
|
| 244 |
+
# Return only the outputs for the active components
|
| 245 |
+
return plot, insights, news, status # Removed merged_df and csv_path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 246 |
|
| 247 |
analyze_button.click(
|
| 248 |
fn=run_analysis_and_prepare_download,
|
| 249 |
inputs=[ticker_input, start_date_input, end_date_input], # Inputs are now textboxes
|
| 250 |
+
# Update outputs list to match the modified return values
|
| 251 |
+
outputs=[plot_output, insights_output, news_output, status_output] # Removed merged_df_state and download_data
|
| 252 |
)
|
| 253 |
|
| 254 |
# --- Launch the App ---
|