Skip to content

Commit b03008e

Browse files
committed
Fix regressions with --lf plugin
Only filter with known failures, and explicitly keep paths of passed arguments. This also displays the "run-last-failure" status before collected files, and does not update the cache with "--collect-only". Fixes #6968.
1 parent 2d9dac9 commit b03008e

File tree

5 files changed

+210
-65
lines changed

5 files changed

+210
-65
lines changed

changelog/6991.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix regressions with `--lf` filtering too much since pytest 5.4.

changelog/6991.improvement.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Collected files are displayed after any reports from hooks, e.g. the status from ``--lf``.

src/_pytest/cacheprovider.py

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -183,27 +183,35 @@ def pytest_make_collect_report(self, collector) -> Generator:
183183
res.result = sorted(
184184
res.result, key=lambda x: 0 if Path(str(x.fspath)) in lf_paths else 1,
185185
)
186-
out.force_result(res)
187186
return
188187

189188
elif isinstance(collector, Module):
190189
if Path(str(collector.fspath)) in self.lfplugin._last_failed_paths:
191190
out = yield
192191
res = out.get_result()
193-
194-
filtered_result = [
195-
x for x in res.result if x.nodeid in self.lfplugin.lastfailed
192+
result = res.result
193+
lastfailed = self.lfplugin.lastfailed
194+
195+
# Only filter with known failures.
196+
if not self._collected_at_least_one_failure:
197+
if not any(x.nodeid in lastfailed for x in result):
198+
return
199+
self.lfplugin.config.pluginmanager.register(
200+
LFPluginCollSkipfiles(self.lfplugin), "lfplugin-collskip"
201+
)
202+
self._collected_at_least_one_failure = True
203+
204+
session = collector.session
205+
result[:] = [
206+
x
207+
for x in result
208+
if x.nodeid in lastfailed
209+
# Include any passed arguments (not trivial to filter).
210+
or session.isinitpath(x.fspath)
211+
# Keep all sub-collectors.
212+
or isinstance(x, nodes.Collector)
196213
]
197-
if filtered_result:
198-
res.result = filtered_result
199-
out.force_result(res)
200-
201-
if not self._collected_at_least_one_failure:
202-
self.lfplugin.config.pluginmanager.register(
203-
LFPluginCollSkipfiles(self.lfplugin), "lfplugin-collskip"
204-
)
205-
self._collected_at_least_one_failure = True
206-
return res
214+
return
207215
yield
208216

209217

@@ -234,8 +242,8 @@ def __init__(self, config: Config) -> None:
234242
self.lastfailed = config.cache.get(
235243
"cache/lastfailed", {}
236244
) # type: Dict[str, bool]
237-
self._previously_failed_count = None
238-
self._report_status = None
245+
self._previously_failed_count = None # type: Optional[int]
246+
self._report_status = None # type: Optional[str]
239247
self._skipped_files = 0 # count skipped files during collection due to --lf
240248

241249
if config.getoption("lf"):
@@ -269,7 +277,12 @@ def pytest_collectreport(self, report):
269277
else:
270278
self.lastfailed[report.nodeid] = True
271279

272-
def pytest_collection_modifyitems(self, session, config, items):
280+
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
281+
def pytest_collection_modifyitems(
282+
self, config: Config, items: List[nodes.Item]
283+
) -> Generator[None, None, None]:
284+
yield
285+
273286
if not self.active:
274287
return
275288

@@ -334,9 +347,12 @@ def __init__(self, config):
334347
self.active = config.option.newfirst
335348
self.cached_nodeids = config.cache.get("cache/nodeids", [])
336349

350+
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
337351
def pytest_collection_modifyitems(
338-
self, session: Session, config: Config, items: List[nodes.Item]
339-
) -> None:
352+
self, items: List[nodes.Item]
353+
) -> Generator[None, None, None]:
354+
yield
355+
340356
new_items = OrderedDict() # type: OrderedDict[str, nodes.Item]
341357
if self.active:
342358
other_items = OrderedDict() # type: OrderedDict[str, nodes.Item]
@@ -358,11 +374,12 @@ def pytest_collection_modifyitems(
358374
def _get_increasing_order(self, items):
359375
return sorted(items, key=lambda item: item.fspath.mtime(), reverse=True)
360376

361-
def pytest_sessionfinish(self, session):
377+
def pytest_sessionfinish(self) -> None:
362378
config = self.config
363379
if config.getoption("cacheshow") or hasattr(config, "slaveinput"):
364380
return
365-
381+
if config.getoption("collectonly"):
382+
return
366383
config.cache.set("cache/nodeids", self.cached_nodeids)
367384

368385

src/_pytest/terminal.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -661,15 +661,17 @@ def pytest_report_header(self, config):
661661
def pytest_collection_finish(self, session):
662662
self.report_collect(True)
663663

664-
if self.config.getoption("collectonly"):
665-
self._printcollecteditems(session.items)
666-
667664
lines = self.config.hook.pytest_report_collectionfinish(
668665
config=self.config, startdir=self.startdir, items=session.items
669666
)
670667
self._write_report_lines_from_hooks(lines)
671668

672669
if self.config.getoption("collectonly"):
670+
if session.items:
671+
if self.config.option.verbose > -1:
672+
self._tw.line("")
673+
self._printcollecteditems(session.items)
674+
673675
failed = self.stats.get("failed")
674676
if failed:
675677
self._tw.sep("!", "collection failures")

0 commit comments

Comments
 (0)