Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

conftest.py: support importorskip at import, make every other outcome exception a usage error

未关闭
#15,142 0 条评论 0 个 reaction 已指派 1 人 在 GitHub 查看

维护者通常 1 天内回复

@RonnyPfannschmidt 已经在做这个了。

开始于 2026年10月6日。

  • #15143 来自 @RonnyPfannschmidt —— 未关闭

评估

这个 Issue 还没有评估数据。

描述

topic: collection

🤖 Written by Claude Opus 5.5 via Claude Code for the pytest maintainers; I prompted it, it did the work, I read it.

Problem

A conftest.py is plugin code, not a collected module. Today an outcome exception raised while importing it does something different depending on how pytest was invoked:

conftest top level pytest tests pytest tests/sub or a node id
pytest.importorskip("missing") directory skipped, exit 0 raw Skipped traceback, exit 1 (#15141)
pytest.skip("x") (no allow_module_level) whole directory skipped, exit 0 (#12371) raw Skipped traceback, exit 1
pytest.fail("x") collection error, exit 2 raw traceback, exit 1
raise unittest.SkipTest("x") collection error, exit 2 collection error

(checked on main @ e84e063)

Why:

  • PytestPluginManager._importconftest wraps except Exception into ConftestImportFailure. OutcomeException derives from BaseException, so Skipped/Failed/XFailed slip past, while unittest.SkipTest (an Exception) is reported as an error.
  • During collection the conftest happens to be imported inside the Dir collector's CallInfo (pytest_make_collect_report in runner.py), so an escaped Skipped becomes a skip of the directory.
  • Initial conftests (_set_initial_conftests, for command-line args) have no collector around them, so the same exception crashes pytest.
  • The allow_module_level check exists only in python.importtestmodule, so a plain pytest.skip("x") in a conftest silently skips a whole package.

Real-world usage

Scan of 1648 conftest.py files in 177 popular repos:

  • Import-time outcome exceptions in conftests: 10 files in 6 repos (pandas, fsspec, kombu, ibis, salt, gunicorn). All of them are pytest.importorskip; there was no top-level pytest.skip/pytest.fail/raise SkipTest in any conftest. Typical: pa = pytest.importorskip("pyarrow") in pandas/tests/arrays/arrow/conftest.py, gating the directory and binding the module for the fixtures below in one line.
  • Alternatives in use are all worse for this job: conditional collect_ignore/collect_ignore_glob (14 repos, silent, a try/except per dependency, does not bind the module), pytest_ignore_collect (7 repos, silent), skip markers added from pytest_collection_modifyitems/pytest_runtest_setup (~12 repos, verbose, does not protect the conftest's own imports).

So importorskip in a conftest is a legitimate, useful idiom; everything else is an accident.

Proposal

  1. Support pytest.importorskip at conftest import. It skips the conftest's directory, consistently: also when the conftest is an initial conftest (command-line path or node id), which fixes #15141. A node id below the skipped directory reports the skip instead of ERROR: found no collectors.
  2. Every other outcome exception at conftest import is a usage error naming the conftest: pytest.skip() (with or without allow_module_level), pytest.fail(), pytest.xfail(). This resolves #12371.
    • pytest.skip() currently "works" during collection, so it gets a PytestRemovedIn10Warning (keeping today's directory skip) in 9.x and becomes the usage error in 10. fail/xfail already error during collection and crash on initial conftests, so they become the usage error right away.
  3. --import-mode=importlib: remove the conftest from sys.modules when its import raises, so a retry never sees a half-executed module (#15141, point 3).

Implementation note: importorskip raises a plain Skipped today, so it needs to be told apart, e.g. a private Skipped subclass or flag set only by importorskip (including its minversion skip).

Not affected: pytest.exit() (Exit is not an OutcomeException), outcome exceptions raised from conftest hooks or fixtures at runtime (node-scoped, already well-defined, see test_skip_file_by_conftest), and skips in a package __init__.py (a collected module, governed by allow_module_level).

Docs

Document importorskip in conftest.py as the supported way to gate a directory on an optional dependency, and state that no other skip/fail is allowed there.

Supersedes #12371 and #15141 (both closed in favour of this). Background: #4479.

主要语言
Python
星标
14.6k
派生
3.5k
平均合并
1 天 21 小时
30 天内合并 PR
29

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

pytest-dev/pytest 的其他 Issue

查看 pytest-dev/pytest 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。