Skip to content

Commit 7478136

Browse files
committed
lint
1 parent 4e0c085 commit 7478136

1 file changed

Lines changed: 85 additions & 93 deletions

File tree

test_polling.py

Lines changed: 85 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,270 +1,262 @@
1-
import pytest
2-
from unittest.mock import Mock, patch
31
from typing import Any
2+
from unittest.mock import Mock, patch
3+
4+
import pytest
45

5-
from src.runloop_api_client.lib.polling import poll_until, PollingConfig, PollingTimeout
6+
from src.runloop_api_client.lib.polling import PollingConfig, PollingTimeout, poll_until
67

78

89
class TestPollingConfig:
910
"""Test PollingConfig dataclass"""
10-
11+
1112
def test_default_config(self):
1213
config = PollingConfig()
1314
assert config.interval_seconds == 1.0
1415
assert config.max_attempts == 120
1516
assert config.timeout_seconds is None
16-
17+
1718
def test_custom_config(self):
18-
config = PollingConfig(
19-
interval_seconds=0.5,
20-
max_attempts=10,
21-
timeout_seconds=30.0
22-
)
19+
config = PollingConfig(interval_seconds=0.5, max_attempts=10, timeout_seconds=30.0)
2320
assert config.interval_seconds == 0.5
2421
assert config.max_attempts == 10
2522
assert config.timeout_seconds == 30.0
2623

2724

2825
class TestPollingTimeout:
2926
"""Test PollingTimeout exception"""
30-
27+
3128
def test_polling_timeout_initialization(self):
3229
last_value = {"status": "running"}
3330
exception = PollingTimeout("Test message", last_value)
34-
31+
3532
assert exception.last_value == last_value
3633
assert "Test message" in str(exception)
3734
assert "Last retrieved value: {'status': 'running'}" in str(exception)
3835

3936

4037
class TestPollUntil:
4138
"""Test poll_until function"""
42-
39+
4340
def test_immediate_success(self):
4441
"""Test when condition is met on first attempt"""
4542
retriever = Mock(return_value="completed")
4643
is_terminal = Mock(return_value=True)
47-
44+
4845
result = poll_until(retriever, is_terminal)
49-
46+
5047
assert result == "completed"
5148
assert retriever.call_count == 1
5249
assert is_terminal.call_count == 1
5350
is_terminal.assert_called_with("completed")
54-
51+
5552
def test_success_after_multiple_attempts(self):
5653
"""Test when condition is met after several attempts"""
5754
values = ["pending", "running", "completed"]
5855
retriever = Mock(side_effect=values)
5956
is_terminal = Mock(side_effect=[False, False, True])
60-
61-
with patch('time.sleep') as mock_sleep:
57+
58+
with patch("time.sleep") as mock_sleep:
6259
result = poll_until(retriever, is_terminal)
63-
60+
6461
assert result == "completed"
6562
assert retriever.call_count == 3
6663
assert is_terminal.call_count == 3
6764
assert mock_sleep.call_count == 2 # Should sleep between attempts
68-
65+
6966
def test_custom_config_interval(self):
7067
"""Test with custom polling interval"""
7168
retriever = Mock(side_effect=["pending", "completed"])
7269
is_terminal = Mock(side_effect=[False, True])
7370
config = PollingConfig(interval_seconds=0.1)
74-
75-
with patch('time.sleep') as mock_sleep:
71+
72+
with patch("time.sleep") as mock_sleep:
7673
result = poll_until(retriever, is_terminal, config)
77-
74+
7875
assert result == "completed"
7976
mock_sleep.assert_called_with(0.1)
80-
77+
8178
def test_max_attempts_exceeded(self):
8279
"""Test when max attempts is exceeded"""
8380
retriever = Mock(return_value="still_running")
8481
is_terminal = Mock(return_value=False)
8582
config = PollingConfig(max_attempts=3, interval_seconds=0.01)
86-
87-
with patch('time.sleep'):
83+
84+
with patch("time.sleep"):
8885
with pytest.raises(PollingTimeout) as exc_info:
8986
poll_until(retriever, is_terminal, config)
90-
87+
9188
assert "Exceeded maximum attempts (3)" in str(exc_info.value)
9289
assert exc_info.value.last_value == "still_running"
9390
assert retriever.call_count == 3
94-
91+
9592
def test_timeout_exceeded(self):
9693
"""Test when timeout is exceeded"""
9794
retriever = Mock(return_value="still_running")
9895
is_terminal = Mock(return_value=False)
9996
config = PollingConfig(timeout_seconds=0.1, interval_seconds=0.01)
100-
97+
10198
# Mock time.time to simulate timeout
10299
start_time = 1000.0
103-
with patch('time.time', side_effect=[start_time, start_time + 0.05, start_time + 0.15]):
104-
with patch('time.sleep'):
100+
with patch("time.time", side_effect=[start_time, start_time + 0.05, start_time + 0.15]):
101+
with patch("time.sleep"):
105102
with pytest.raises(PollingTimeout) as exc_info:
106103
poll_until(retriever, is_terminal, config)
107-
104+
108105
assert "Exceeded timeout of 0.1 seconds" in str(exc_info.value)
109106
assert exc_info.value.last_value == "still_running"
110-
107+
111108
def test_error_without_handler(self):
112109
"""Test that exceptions are re-raised when no error handler is provided"""
113110
retriever = Mock(side_effect=ValueError("Test error"))
114111
is_terminal = Mock(return_value=False)
115-
112+
116113
with pytest.raises(ValueError, match="Test error"):
117114
poll_until(retriever, is_terminal)
118-
115+
119116
def test_error_with_handler_continue(self):
120117
"""Test error handler that allows polling to continue"""
121118
retriever = Mock(side_effect=[ValueError("Test error"), "recovered"])
122119
is_terminal = Mock(side_effect=[False, True])
123-
124-
def error_handler(e: Exception) -> str:
120+
121+
def error_handler(_: Exception) -> str:
125122
return "error_handled"
126-
127-
with patch('time.sleep'):
123+
124+
with patch("time.sleep"):
128125
result = poll_until(retriever, is_terminal, on_error=error_handler)
129-
126+
130127
assert result == "recovered"
131128
assert retriever.call_count == 2
132129
assert is_terminal.call_count == 2
133-
130+
134131
def test_error_with_handler_reraise(self):
135132
"""Test error handler that re-raises the exception"""
136133
retriever = Mock(side_effect=ValueError("Test error"))
137134
is_terminal = Mock(return_value=False)
138-
135+
139136
def error_handler(e: Exception) -> None:
140137
raise e
141-
138+
142139
with pytest.raises(ValueError, match="Test error"):
143140
poll_until(retriever, is_terminal, on_error=error_handler)
144-
141+
145142
def test_error_handler_return_terminal_value(self):
146143
"""Test error handler that returns a terminal value"""
147144
retriever = Mock(side_effect=ValueError("Test error"))
148145
is_terminal = Mock(side_effect=[True]) # Terminal condition met on error handler return
149-
150-
def error_handler(e: Exception) -> str:
146+
147+
def error_handler(_: Exception) -> str:
151148
return "error_terminal"
152-
149+
153150
result = poll_until(retriever, is_terminal, on_error=error_handler)
154-
151+
155152
assert result == "error_terminal"
156153
assert retriever.call_count == 1
157154
assert is_terminal.call_count == 1
158-
155+
159156
def test_multiple_errors_with_handler(self):
160157
"""Test multiple errors with handler"""
161-
retriever = Mock(side_effect=[
162-
ValueError("Error 1"),
163-
RuntimeError("Error 2"),
164-
"success"
165-
])
158+
retriever = Mock(side_effect=[ValueError("Error 1"), RuntimeError("Error 2"), "success"])
166159
is_terminal = Mock(side_effect=[False, False, True])
167-
160+
168161
error_count = 0
169-
def error_handler(e: Exception) -> str:
162+
163+
def error_handler(_: Exception) -> str:
170164
nonlocal error_count
171165
error_count += 1
172166
return f"handled_error_{error_count}"
173-
174-
with patch('time.sleep'):
167+
168+
with patch("time.sleep"):
175169
result = poll_until(retriever, is_terminal, on_error=error_handler)
176-
170+
177171
assert result == "success"
178172
assert error_count == 2
179173
assert retriever.call_count == 3
180-
174+
181175
def test_none_values_handling(self):
182176
"""Test handling of None values"""
183177
retriever = Mock(side_effect=[None, None, "final"])
184178
is_terminal = Mock(side_effect=[False, False, True])
185-
186-
with patch('time.sleep'):
179+
180+
with patch("time.sleep"):
187181
result = poll_until(retriever, is_terminal)
188-
182+
189183
assert result == "final"
190184
assert retriever.call_count == 3
191-
185+
192186
def test_complex_object_polling(self):
193187
"""Test polling with complex objects"""
188+
194189
class Status:
195190
def __init__(self, state: str, progress: int):
196191
self.state = state
197192
self.progress = progress
198-
199-
statuses = [
200-
Status("starting", 0),
201-
Status("running", 50),
202-
Status("completed", 100)
203-
]
204-
193+
194+
statuses = [Status("starting", 0), Status("running", 50), Status("completed", 100)]
195+
205196
retriever = Mock(side_effect=statuses)
206197
is_terminal = Mock(side_effect=[False, False, True])
207-
208-
with patch('time.sleep'):
198+
199+
with patch("time.sleep"):
209200
result = poll_until(retriever, is_terminal)
210-
201+
211202
assert result.state == "completed"
212203
assert result.progress == 100
213-
204+
214205
def test_zero_max_attempts(self):
215206
"""Test with zero max attempts"""
216207
retriever = Mock(return_value="value")
217208
is_terminal = Mock(return_value=False)
218209
config = PollingConfig(max_attempts=0)
219-
210+
220211
with pytest.raises(PollingTimeout) as exc_info:
221212
poll_until(retriever, is_terminal, config)
222-
213+
223214
assert "Exceeded maximum attempts (0)" in str(exc_info.value)
224215
assert retriever.call_count == 1 # Retriever is called once, then attempts check happens
225-
216+
226217
def test_negative_interval(self):
227218
"""Test with negative interval (should still work)"""
228219
retriever = Mock(side_effect=["first", "second"])
229220
is_terminal = Mock(side_effect=[False, True])
230221
config = PollingConfig(interval_seconds=-0.1)
231-
232-
with patch('time.sleep') as mock_sleep:
222+
223+
with patch("time.sleep") as mock_sleep:
233224
result = poll_until(retriever, is_terminal, config)
234-
225+
235226
assert result == "second"
236227
mock_sleep.assert_called_with(-0.1)
237-
228+
238229
def test_both_timeout_and_max_attempts(self):
239230
"""Test when both timeout and max_attempts are set"""
240231
retriever = Mock(return_value="still_running")
241232
is_terminal = Mock(return_value=False)
242233
config = PollingConfig(max_attempts=5, timeout_seconds=0.1, interval_seconds=0.01)
243-
234+
244235
# Mock time to hit timeout before max_attempts
245236
start_time = 1000.0
246-
with patch('time.time', side_effect=[start_time, start_time + 0.05, start_time + 0.15]):
247-
with patch('time.sleep'):
237+
with patch("time.time", side_effect=[start_time, start_time + 0.05, start_time + 0.15]):
238+
with patch("time.sleep"):
248239
with pytest.raises(PollingTimeout) as exc_info:
249240
poll_until(retriever, is_terminal, config)
250-
241+
251242
# Should hit timeout first
252243
assert "Exceeded timeout of 0.1 seconds" in str(exc_info.value)
253244
assert retriever.call_count == 2 # Called twice before timeout
254-
245+
255246
def test_terminal_condition_changes(self):
256247
"""Test when terminal condition logic changes during polling"""
257248
retriever = Mock(side_effect=["value1", "value2", "value3"])
258-
249+
259250
call_count = 0
260-
def dynamic_terminal(value: Any) -> bool:
251+
252+
def dynamic_terminal(_: Any) -> bool:
261253
nonlocal call_count
262254
call_count += 1
263255
# First two calls return False, third returns True
264256
return call_count >= 3
265-
266-
with patch('time.sleep'):
257+
258+
with patch("time.sleep"):
267259
result = poll_until(retriever, dynamic_terminal)
268-
260+
269261
assert result == "value3"
270-
assert retriever.call_count == 3
262+
assert retriever.call_count == 3

0 commit comments

Comments
 (0)