@@ -60,37 +60,37 @@ def test_cache_set_and_get(self):
6060 """Test that we can set and retrieve cached values."""
6161 test_data = '{"success": true, "ticker": "SWDA"}'
6262 _set_cached_analysis ("SWDA" , 10 , test_data )
63-
63+
6464 result = _get_cached_analysis ("SWDA" , 10 )
6565 assert result == test_data
6666
6767 def test_cache_different_tickers (self ):
6868 """Test that cache correctly handles different tickers."""
6969 data1 = '{"success": true, "ticker": "SWDA"}'
7070 data2 = '{"success": true, "ticker": "AAPL"}'
71-
71+
7272 _set_cached_analysis ("SWDA" , 10 , data1 )
7373 _set_cached_analysis ("AAPL" , 10 , data2 )
74-
74+
7575 assert _get_cached_analysis ("SWDA" , 10 ) == data1
7676 assert _get_cached_analysis ("AAPL" , 10 ) == data2
7777
7878 def test_cache_different_years (self ):
7979 """Test that cache correctly handles different year periods."""
8080 data1 = '{"success": true, "years": 5}'
8181 data2 = '{"success": true, "years": 10}'
82-
82+
8383 _set_cached_analysis ("SWDA" , 5 , data1 )
8484 _set_cached_analysis ("SWDA" , 10 , data2 )
85-
85+
8686 assert _get_cached_analysis ("SWDA" , 5 ) == data1
8787 assert _get_cached_analysis ("SWDA" , 10 ) == data2
8888
8989 def test_cache_uppercase_normalization (self ):
9090 """Test that cache normalizes ticker case."""
9191 test_data = '{"success": true, "ticker": "SWDA"}'
9292 _set_cached_analysis ("swda" , 10 , test_data )
93-
93+
9494 # Should be able to retrieve with different case
9595 result = _get_cached_analysis ("SWDA" , 10 )
9696 assert result == test_data
@@ -107,139 +107,133 @@ def teardown_method(self):
107107 """Clear cache after each test."""
108108 _CACHE .clear ()
109109
110- @patch (' src.tools.analyze_financial_asset._search_and_resolve_symbol' )
111- @patch (' src.tools.analyze_financial_asset._get_historical_prices_internal' )
112- @patch (' src.tools.analyze_financial_asset._calculate_returns_internal' )
110+ @patch (" src.tools.analyze_financial_asset._search_and_resolve_symbol" )
111+ @patch (" src.tools.analyze_financial_asset._get_historical_prices_internal" )
112+ @patch (" src.tools.analyze_financial_asset._calculate_returns_internal" )
113113 def test_cache_miss_calls_functions (
114114 self , mock_calc_returns , mock_get_prices , mock_search_symbol
115115 ):
116116 """Test that on cache miss, all internal functions are called."""
117117 # Setup mocks
118118 mock_search_symbol .return_value = MagicMock (
119- success = True ,
120- found_symbol = "SWDA.DE" ,
121- company_name = "Test ETF"
119+ success = True , found_symbol = "SWDA.DE" , company_name = "Test ETF"
122120 )
123121 mock_get_prices .return_value = {
124122 "success" : True ,
125123 "prices" : [
126124 {"date" : "2020-01-01" , "close_price" : 100.0 },
127- {"date" : "2021-01-01" , "close_price" : 110.0 }
125+ {"date" : "2021-01-01" , "close_price" : 110.0 },
128126 ],
129127 "data_points" : 2 ,
130128 "years_available" : 1.0 ,
131129 "start_date" : "2020-01-01" ,
132- "end_date" : "2021-01-01"
130+ "end_date" : "2021-01-01" ,
133131 }
134132 mock_calc_returns .return_value = {
135133 "success" : True ,
136134 "returns" : {"1_year" : 10.0 },
137- "total_return" : 10.0
135+ "total_return" : 10.0 ,
138136 }
139137
140138 # First call should miss cache and call functions
141139 result1 = analyze_financial_asset ("SWDA" , years = 10 , use_cache = True )
142-
140+
143141 # Verify functions were called
144142 assert mock_search_symbol .called
145143 assert mock_get_prices .called
146144 assert mock_calc_returns .called
147-
145+
148146 # Verify result is valid JSON
149147 data = json .loads (result1 )
150148 assert data ["success" ] is True
151149 assert data ["ticker" ] == "SWDA"
152150
153- @patch (' src.tools.analyze_financial_asset._search_and_resolve_symbol' )
154- @patch (' src.tools.analyze_financial_asset._get_historical_prices_internal' )
155- @patch (' src.tools.analyze_financial_asset._calculate_returns_internal' )
151+ @patch (" src.tools.analyze_financial_asset._search_and_resolve_symbol" )
152+ @patch (" src.tools.analyze_financial_asset._get_historical_prices_internal" )
153+ @patch (" src.tools.analyze_financial_asset._calculate_returns_internal" )
156154 def test_cache_hit_skips_functions (
157155 self , mock_calc_returns , mock_get_prices , mock_search_symbol
158156 ):
159157 """Test that on cache hit, internal functions are not called."""
160158 # Setup mocks for first call
161159 mock_search_symbol .return_value = MagicMock (
162- success = True ,
163- found_symbol = "SWDA.DE" ,
164- company_name = "Test ETF"
160+ success = True , found_symbol = "SWDA.DE" , company_name = "Test ETF"
165161 )
166162 mock_get_prices .return_value = {
167163 "success" : True ,
168164 "prices" : [
169165 {"date" : "2020-01-01" , "close_price" : 100.0 },
170- {"date" : "2021-01-01" , "close_price" : 110.0 }
166+ {"date" : "2021-01-01" , "close_price" : 110.0 },
171167 ],
172168 "data_points" : 2 ,
173169 "years_available" : 1.0 ,
174170 "start_date" : "2020-01-01" ,
175- "end_date" : "2021-01-01"
171+ "end_date" : "2021-01-01" ,
176172 }
177173 mock_calc_returns .return_value = {
178174 "success" : True ,
179175 "returns" : {"1_year" : 10.0 },
180- "total_return" : 10.0
176+ "total_return" : 10.0 ,
181177 }
182178
183179 # First call - cache miss
184180 result1 = analyze_financial_asset ("SWDA" , years = 10 , use_cache = True )
185-
181+
186182 # Reset mock call counts
187183 mock_search_symbol .reset_mock ()
188184 mock_get_prices .reset_mock ()
189185 mock_calc_returns .reset_mock ()
190-
186+
191187 # Second call - should hit cache
192188 result2 = analyze_financial_asset ("SWDA" , years = 10 , use_cache = True )
193-
189+
194190 # Verify functions were NOT called on second attempt
195191 assert not mock_search_symbol .called
196192 assert not mock_get_prices .called
197193 assert not mock_calc_returns .called
198-
194+
199195 # Results should be identical
200196 assert result1 == result2
201197
202- @patch (' src.tools.analyze_financial_asset._search_and_resolve_symbol' )
203- @patch (' src.tools.analyze_financial_asset._get_historical_prices_internal' )
204- @patch (' src.tools.analyze_financial_asset._calculate_returns_internal' )
198+ @patch (" src.tools.analyze_financial_asset._search_and_resolve_symbol" )
199+ @patch (" src.tools.analyze_financial_asset._get_historical_prices_internal" )
200+ @patch (" src.tools.analyze_financial_asset._calculate_returns_internal" )
205201 def test_use_cache_false_bypasses_cache (
206202 self , mock_calc_returns , mock_get_prices , mock_search_symbol
207203 ):
208204 """Test that use_cache=False bypasses the cache."""
209205 # Setup mocks
210206 mock_search_symbol .return_value = MagicMock (
211- success = True ,
212- found_symbol = "SWDA.DE" ,
213- company_name = "Test ETF"
207+ success = True , found_symbol = "SWDA.DE" , company_name = "Test ETF"
214208 )
215209 mock_get_prices .return_value = {
216210 "success" : True ,
217211 "prices" : [
218212 {"date" : "2020-01-01" , "close_price" : 100.0 },
219- {"date" : "2021-01-01" , "close_price" : 110.0 }
213+ {"date" : "2021-01-01" , "close_price" : 110.0 },
220214 ],
221215 "data_points" : 2 ,
222216 "years_available" : 1.0 ,
223217 "start_date" : "2020-01-01" ,
224- "end_date" : "2021-01-01"
218+ "end_date" : "2021-01-01" ,
225219 }
226220 mock_calc_returns .return_value = {
227221 "success" : True ,
228222 "returns" : {"1_year" : 10.0 },
229- "total_return" : 10.0
223+ "total_return" : 10.0 ,
230224 }
231225
232226 # First call with caching
233227 result1 = analyze_financial_asset ("SWDA" , years = 10 , use_cache = True )
234-
228+
235229 # Reset mocks
236230 mock_search_symbol .reset_mock ()
237231 mock_get_prices .reset_mock ()
238232 mock_calc_returns .reset_mock ()
239-
233+
240234 # Second call with use_cache=False should call functions again
241235 result2 = analyze_financial_asset ("SWDA" , years = 10 , use_cache = False )
242-
236+
243237 # Verify functions WERE called even though data is cached
244238 assert mock_search_symbol .called
245239 assert mock_get_prices .called
@@ -250,7 +244,7 @@ def test_cache_respects_case_insensitive_ticker(self):
250244 # Pre-populate cache with lowercase ticker
251245 test_data = '{"success": true, "ticker": "swda"}'
252246 _set_cached_analysis ("swda" , 10 , test_data )
253-
247+
254248 # Request with uppercase should hit the same cache
255249 result = _get_cached_analysis ("SWDA" , 10 )
256250 assert result == test_data
@@ -273,30 +267,32 @@ def test_streamlit_cache_storage(self):
273267 mock_st_module = MagicMock ()
274268 mock_session_state = MagicMock ()
275269 mock_st_module .session_state = mock_session_state
276-
270+
277271 # Patch the import
278- with patch .dict (' sys.modules' , {' streamlit' : mock_st_module }):
272+ with patch .dict (" sys.modules" , {" streamlit" : mock_st_module }):
279273 test_data = '{"success": true, "ticker": "SWDA"}'
280274 _set_cached_analysis ("SWDA" , 10 , test_data )
281-
275+
282276 # Verify that financial_asset_cache was created and data was stored
283277 # The session_state should have been accessed to set the cache
284- assert mock_session_state .financial_asset_cache .__setitem__ .called or \
285- hasattr (mock_session_state , 'financial_asset_cache' )
278+ assert (
279+ mock_session_state .financial_asset_cache .__setitem__ .called
280+ or hasattr (mock_session_state , "financial_asset_cache" )
281+ )
286282
287283 def test_streamlit_cache_retrieval (self ):
288284 """Test that cache is retrieved from Streamlit session state when available."""
289285 # Create a mock streamlit module with pre-cached data
290286 test_data = '{"success": true, "ticker": "SWDA"}'
291-
287+
292288 mock_st_module = MagicMock ()
293289 mock_session_state = MagicMock ()
294290 # Configure the mock to have the cache
295291 mock_session_state .financial_asset_cache = {"SWDA_10" : test_data }
296292 mock_st_module .session_state = mock_session_state
297-
293+
298294 # Patch the import
299- with patch .dict (' sys.modules' , {' streamlit' : mock_st_module }):
295+ with patch .dict (" sys.modules" , {" streamlit" : mock_st_module }):
300296 result = _get_cached_analysis ("SWDA" , 10 )
301297 assert result == test_data
302298
@@ -305,11 +301,11 @@ def test_fallback_to_module_cache_when_no_streamlit(self):
305301 # Store data in module cache
306302 test_data = '{"success": true, "ticker": "SWDA"}'
307303 _set_cached_analysis ("SWDA" , 10 , test_data )
308-
304+
309305 # Retrieve should work even without Streamlit
310306 result = _get_cached_analysis ("SWDA" , 10 )
311307 assert result == test_data
312-
308+
313309 # Verify it's in module cache
314310 assert "SWDA_10" in _CACHE
315311 assert _CACHE ["SWDA_10" ] == test_data
0 commit comments