|
7 | 7 | import sys
|
8 | 8 | import traceback
|
9 | 9 | from typing import Any
|
| 10 | +from typing import Callable |
10 | 11 | from typing import Sequence
|
11 | 12 | import warnings
|
12 | 13 |
|
@@ -60,14 +61,14 @@ def __init__(self, config: pytest.Config) -> None:
|
60 | 61 | self._failed_collection_errors: dict[object, bool] = {}
|
61 | 62 | self._active_nodes: set[WorkerController] = set()
|
62 | 63 | self._failed_nodes_count = 0
|
63 |
| - self.saved_put = None |
| 64 | + self.saved_put: Callable[[tuple[str, dict[str, Any]]], None] |
64 | 65 | self.remake_nodes = False
|
65 | 66 | self.ready_to_run_tests = False
|
66 | 67 | self._max_worker_restart = get_default_max_worker_restart(self.config)
|
67 | 68 | # summary message to print at the end of the session
|
68 | 69 | self._summary_report: str | None = None
|
69 | 70 | self.terminal = config.pluginmanager.getplugin("terminalreporter")
|
70 |
| - self.worker_status: dict[WorkerController, str] = {} |
| 71 | + self.worker_status: dict[str, str] = {} |
71 | 72 | if self.terminal:
|
72 | 73 | self.trdist = TerminalDistReporter(config)
|
73 | 74 | config.pluginmanager.register(self.trdist, "terminaldistreporter")
|
@@ -180,63 +181,71 @@ def loop_once(self) -> None:
|
180 | 181 | self.triggershutdown()
|
181 | 182 |
|
182 | 183 |
|
183 |
| - def is_node_finishing(self, node: WorkerController): |
| 184 | + def is_node_finishing(self, node: WorkerController) -> bool: |
184 | 185 | """Check if a test worker is considered to be finishing.
|
185 | 186 |
|
186 | 187 | Evaluate whether it's on its last test, or if no tests are pending.
|
187 | 188 | """
|
| 189 | + assert self.sched is not None |
188 | 190 | pending = self.sched.node2pending.get(node)
|
189 | 191 | return pending is not None and len(pending) < 2
|
190 | 192 |
|
191 | 193 |
|
192 |
| - def is_node_clear(self, node: WorkerController): |
| 194 | + def is_node_clear(self, node: WorkerController) -> bool: |
193 | 195 | """Check if a test worker has no pending tests."""
|
| 196 | + assert self.sched is not None |
194 | 197 | pending = self.sched.node2pending.get(node)
|
195 | 198 | return pending is None or len(pending) == 0
|
196 | 199 |
|
197 | 200 |
|
198 |
| - def are_all_nodes_finishing(self): |
| 201 | + def are_all_nodes_finishing(self) -> bool: |
199 | 202 | """Check if all workers are finishing (See 'is_node_finishing' above)."""
|
| 203 | + assert self.sched is not None |
200 | 204 | return all(self.is_node_finishing(node) for node in self.sched.nodes)
|
201 | 205 |
|
202 | 206 |
|
203 |
| - def are_all_nodes_done(self): |
| 207 | + def are_all_nodes_done(self) -> bool: |
204 | 208 | """Check if all nodes have reported to finish."""
|
205 | 209 | return all(s == "finished" for s in self.worker_status.values())
|
206 | 210 |
|
207 | 211 |
|
208 |
| - def are_all_active_nodes_collected(self): |
| 212 | + def are_all_active_nodes_collected(self) -> bool: |
209 | 213 | """Check if all nodes have reported collection to be complete."""
|
210 | 214 | if not all(n.gateway.id in self.worker_status for n in self._active_nodes):
|
211 | 215 | return False
|
212 | 216 | return all(self.worker_status[n.gateway.id] == "collected" for n in self._active_nodes)
|
213 | 217 |
|
214 | 218 |
|
215 |
| - def reset_nodes_if_needed(self): |
| 219 | + def reset_nodes_if_needed(self) -> None: |
| 220 | + assert self.sched is not None |
216 | 221 | if self.are_all_nodes_finishing() and self.ready_to_run_tests and not self.sched.do_resched:
|
217 | 222 | self.reset_nodes()
|
218 | 223 |
|
219 | 224 |
|
220 |
| - def reset_nodes(self): |
| 225 | + def reset_nodes(self) -> None: |
221 | 226 | """Issue shutdown notices to workers for rescheduling purposes."""
|
| 227 | + assert self.sched is not None |
222 | 228 | if len(self.sched.pending) != 0:
|
223 | 229 | self.remake_nodes = True
|
224 | 230 | for node in self.sched.nodes:
|
225 | 231 | if self.is_node_finishing(node):
|
226 | 232 | node.shutdown()
|
227 | 233 |
|
228 | 234 |
|
229 |
| - def reschedule(self): |
| 235 | + def reschedule(self) -> None: |
230 | 236 | """Reschedule tests."""
|
| 237 | + assert self.sched is not None |
231 | 238 | self.sched.do_resched = False
|
232 | 239 | self.sched.check_schedule(self.sched.nodes[0], 1.0, True)
|
233 | 240 |
|
234 | 241 |
|
235 |
| - def prepare_for_reschedule(self): |
| 242 | + def prepare_for_reschedule(self) -> None: |
236 | 243 | """Update test workers and their status tracking so rescheduling is ready."""
|
| 244 | + assert self.sched is not None |
237 | 245 | self.remake_nodes = False
|
238 | 246 | num_workers = self.sched.dist_groups[self.sched.pending_groups[0]]['group_workers']
|
239 | 247 | self.trdist._status = {}
|
| 248 | + assert self.nodemanager is not None |
240 | 249 | new_nodes = self.nodemanager.setup_nodes(self.saved_put, num_workers)
|
241 | 250 | self.worker_status = {}
|
242 | 251 | self._active_nodes = set()
|
@@ -310,7 +319,7 @@ def worker_workerfinished(self, node: WorkerController) -> None:
|
310 | 319 | assert not crashitem, (crashitem, node)
|
311 | 320 | self._active_nodes.remove(node)
|
312 | 321 |
|
313 |
| - def update_worker_status(self, node, status): |
| 322 | + def update_worker_status(self, node: WorkerController, status: str) -> None: |
314 | 323 | """Track the worker status.
|
315 | 324 |
|
316 | 325 | Can be used at callbacks like 'worker_workerfinished' so we remember wchic event
|
|
0 commit comments