conftest.py: support importorskip at import, make every other outcome exception a usage error
Los mantenedores suelen responder en 1 día
@RonnyPfannschmidt ya está trabajando en esto.
Desde el 6/10/2026.
- #15143 de @RonnyPfannschmidt — abierto
Evaluación
Este issue todavía no se ha evaluado.
Descripción
🤖 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._importconftestwrapsexcept ExceptionintoConftestImportFailure.OutcomeExceptionderives fromBaseException, soSkipped/Failed/XFailedslip past, whileunittest.SkipTest(anException) is reported as an error.- During collection the conftest happens to be imported inside the
Dircollector'sCallInfo(pytest_make_collect_reportinrunner.py), so an escapedSkippedbecomes 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_levelcheck exists only inpython.importtestmodule, so a plainpytest.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-levelpytest.skip/pytest.fail/raise SkipTestin any conftest. Typical:pa = pytest.importorskip("pyarrow")inpandas/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 frompytest_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
- Support
pytest.importorskipat 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 ofERROR: found no collectors. - Every other outcome exception at conftest import is a usage error naming the conftest:
pytest.skip()(with or withoutallow_module_level),pytest.fail(),pytest.xfail(). This resolves #12371.pytest.skip()currently "works" during collection, so it gets aPytestRemovedIn10Warning(keeping today's directory skip) in 9.x and becomes the usage error in 10.fail/xfailalready error during collection and crash on initial conftests, so they become the usage error right away.
--import-mode=importlib: remove the conftest fromsys.moduleswhen 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.
- Lenguaje dominante
- Python
- Estrellas
- 14.6k
- Forks
- 3.5k
- Merge medio
- 2 d 5 h
- PR fusionados (30 d)
- 27
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de pytest-dev/pytest
-
monkeypatch.setattr fails to undo on objects with a custom __setattr__ (regression from #14969)Posiblemente ocupada @Maurenz2530 la tomó hace 12 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
pytest-dev/pytest#15099 · 6 comentarios ·
Los mantenedores suelen responder en 1 día
-
Allow dotted test filenames (`*.test.py`) via one-line change to `compute_module_name`Quizá libre de nuevo @siddy-stack la tomó hace 51 días y no hay ningún pull request abierto. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 86/100
pytest-dev/pytest#14514 · 6 comentarios ·
Los mantenedores suelen responder en 1 día
-
Expose CaptureManager as public APIQuizá libre de nuevo @harsh21234i la tomó hace 189 días y no hay ningún pull request abierto. Abiertotype: enhancement type: feature-branch
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
pytest-dev/pytest#14186 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
Docs on warnings filters should note that `ResourceWarning` is often delayedPosiblemente ocupada @tanishmisra9 la tomó hace 107 días. Abiertotype: docs
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
pytest-dev/pytest#9825 · 7 comentarios ·
Los mantenedores suelen responder en 1 día
-
Native TOML numeric faulthandler_timeout is rejectedPosiblemente ocupada @hfycium la tomó hace 3 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 25/100
pytest-dev/pytest#15132 ·
Los mantenedores suelen responder en 1 día
Todos los issues de pytest-dev/pytest
Issues similares
-
[Bug]: `graphify export svg` writes a graph.svg that is not well-formed XML when a label contains a control characterPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Graphify-Labs/graphify#4241 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 72/100
-
DeviceTrackerAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 63/100
XiaoMi/ha_xiaomi_home#1821 ·
Los mantenedores suelen responder en 1 día
-
Maven path-index: "Ambiguous or noncanonical artifact path" error does not report the offending pathAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
pulp/pulp_maven#524 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día