Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

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

Đang mở
#15,142 0 bình luận 0 reaction 1 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@RonnyPfannschmidt đang làm issue này rồi.

Từ ngày 6/10/2026.

  • #15143 của @RonnyPfannschmidt — đang mở

Đánh giá

Issue này chưa được đánh giá.

Mô tả

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.

Ngôn ngữ chính
Python
Star
14.6k
Fork
3.5k
Merge trung bình
2 ngày 6 giờ
Pull request đã merge (30 ngày)
31

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của pytest-dev/pytest

Tất cả issue của pytest-dev/pytest

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.