| 241 | |
| 242 | |
| 243 | class LFPluginCollWrapper: |
| 244 | def __init__(self, lfplugin: LFPlugin) -> None: |
| 245 | self.lfplugin = lfplugin |
| 246 | self._collected_at_least_one_failure = False |
| 247 | |
| 248 | @hookimpl(wrapper=True) |
| 249 | def pytest_make_collect_report( |
| 250 | self, collector: nodes.Collector |
| 251 | ) -> Generator[None, CollectReport, CollectReport]: |
| 252 | res = yield |
| 253 | if isinstance(collector, Session | Directory): |
| 254 | class="cm"># Sort any lf-paths to the beginning. |
| 255 | lf_paths = self.lfplugin._last_failed_paths |
| 256 | |
| 257 | class="cm"># Use stable sort to prioritize last failed. |
| 258 | def sort_key(node: nodes.Item | nodes.Collector) -> bool: |
| 259 | return node.path in lf_paths |
| 260 | |
| 261 | res.result = sorted( |
| 262 | res.result, |
| 263 | key=sort_key, |
| 264 | reverse=True, |
| 265 | ) |
| 266 | |
| 267 | elif isinstance(collector, File): |
| 268 | if collector.path in self.lfplugin._last_failed_paths: |
| 269 | result = res.result |
| 270 | lastfailed = self.lfplugin.lastfailed |
| 271 | |
| 272 | class="cm"># Only filter with known failures. |
| 273 | if not self._collected_at_least_one_failure: |
| 274 | if not any(x.nodeid in lastfailed for x in result): |
| 275 | return res |
| 276 | self.lfplugin.config.pluginmanager.register( |
| 277 | LFPluginCollSkipfiles(self.lfplugin), class="st">"lfplugin-collskip" |
| 278 | ) |
| 279 | self._collected_at_least_one_failure = True |
| 280 | |
| 281 | session = collector.session |
| 282 | result[:] = [ |
| 283 | x |
| 284 | for x in result |
| 285 | if x.nodeid in lastfailed |
| 286 | class="cm"># Include any passed arguments (not trivial to filter). |
| 287 | or session.isinitpath(x.path) |
| 288 | class="cm"># Keep all sub-collectors. |
| 289 | or isinstance(x, nodes.Collector) |
| 290 | ] |
| 291 | |
| 292 | return res |
| 293 | |
| 294 | |
| 295 | class LFPluginCollSkipfiles: |