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 ---
|