Move ExitCode's definition from _pytest.main to _pytest.config
ExitCode is used in several internal modules and hooks and so with type annotations added, needs to be imported a lot. _pytest.main, being the entry point, generally sits at the top of the import tree. So, it's not great to have ExitCode defined in _pytest.main, because it will cause a lot of import cycles once type annotations are added (in fact there is already one, which this change removes). Move it to _pytest.config instead. _pytest.main still imports ExitCode, so importing from there still works, although external users should really be importing from `pytest`.
This commit is contained in:
parent
1ebca37689
commit
d33da078a8
|
@ -738,7 +738,7 @@ ExceptionInfo
|
||||||
pytest.ExitCode
|
pytest.ExitCode
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: _pytest.main.ExitCode
|
.. autoclass:: _pytest.config.ExitCode
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ Running ``pytest`` can result in six different exit codes:
|
||||||
:Exit code 4: pytest command line usage error
|
:Exit code 4: pytest command line usage error
|
||||||
:Exit code 5: No tests were collected
|
:Exit code 5: No tests were collected
|
||||||
|
|
||||||
They are represented by the :class:`_pytest.main.ExitCode` enum. The exit codes being a part of the public API can be imported and accessed directly using:
|
They are represented by the :class:`_pytest.config.ExitCode` enum. The exit codes being a part of the public API can be imported and accessed directly using:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
""" command line options, ini-file and conftest.py processing. """
|
""" command line options, ini-file and conftest.py processing. """
|
||||||
import argparse
|
import argparse
|
||||||
import copy
|
import copy
|
||||||
|
import enum
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
import shlex
|
import shlex
|
||||||
|
@ -61,6 +62,29 @@ hookimpl = HookimplMarker("pytest")
|
||||||
hookspec = HookspecMarker("pytest")
|
hookspec = HookspecMarker("pytest")
|
||||||
|
|
||||||
|
|
||||||
|
class ExitCode(enum.IntEnum):
|
||||||
|
"""
|
||||||
|
.. versionadded:: 5.0
|
||||||
|
|
||||||
|
Encodes the valid exit codes by pytest.
|
||||||
|
|
||||||
|
Currently users and plugins may supply other exit codes as well.
|
||||||
|
"""
|
||||||
|
|
||||||
|
#: tests passed
|
||||||
|
OK = 0
|
||||||
|
#: tests failed
|
||||||
|
TESTS_FAILED = 1
|
||||||
|
#: pytest was interrupted
|
||||||
|
INTERRUPTED = 2
|
||||||
|
#: an internal error got in the way
|
||||||
|
INTERNAL_ERROR = 3
|
||||||
|
#: pytest was misused
|
||||||
|
USAGE_ERROR = 4
|
||||||
|
#: pytest couldn't find tests
|
||||||
|
NO_TESTS_COLLECTED = 5
|
||||||
|
|
||||||
|
|
||||||
class ConftestImportFailure(Exception):
|
class ConftestImportFailure(Exception):
|
||||||
def __init__(self, path, excinfo):
|
def __init__(self, path, excinfo):
|
||||||
Exception.__init__(self, path, excinfo)
|
Exception.__init__(self, path, excinfo)
|
||||||
|
@ -68,7 +92,7 @@ class ConftestImportFailure(Exception):
|
||||||
self.excinfo = excinfo # type: Tuple[Type[Exception], Exception, TracebackType]
|
self.excinfo = excinfo # type: Tuple[Type[Exception], Exception, TracebackType]
|
||||||
|
|
||||||
|
|
||||||
def main(args=None, plugins=None) -> "Union[int, _pytest.main.ExitCode]":
|
def main(args=None, plugins=None) -> Union[int, ExitCode]:
|
||||||
""" return exit code, after performing an in-process test run.
|
""" return exit code, after performing an in-process test run.
|
||||||
|
|
||||||
:arg args: list of command line arguments.
|
:arg args: list of command line arguments.
|
||||||
|
@ -76,8 +100,6 @@ def main(args=None, plugins=None) -> "Union[int, _pytest.main.ExitCode]":
|
||||||
:arg plugins: list of plugin objects to be auto-registered during
|
:arg plugins: list of plugin objects to be auto-registered during
|
||||||
initialization.
|
initialization.
|
||||||
"""
|
"""
|
||||||
from _pytest.main import ExitCode
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
config = _prepareconfig(args, plugins)
|
config = _prepareconfig(args, plugins)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
""" core implementation of testing process: init, session, runtest loop. """
|
""" core implementation of testing process: init, session, runtest loop. """
|
||||||
import enum
|
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import functools
|
import functools
|
||||||
import importlib
|
import importlib
|
||||||
|
@ -21,6 +20,7 @@ from _pytest import nodes
|
||||||
from _pytest.compat import TYPE_CHECKING
|
from _pytest.compat import TYPE_CHECKING
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.config import directory_arg
|
from _pytest.config import directory_arg
|
||||||
|
from _pytest.config import ExitCode
|
||||||
from _pytest.config import hookimpl
|
from _pytest.config import hookimpl
|
||||||
from _pytest.config import UsageError
|
from _pytest.config import UsageError
|
||||||
from _pytest.fixtures import FixtureManager
|
from _pytest.fixtures import FixtureManager
|
||||||
|
@ -36,29 +36,6 @@ if TYPE_CHECKING:
|
||||||
from _pytest.python import Package
|
from _pytest.python import Package
|
||||||
|
|
||||||
|
|
||||||
class ExitCode(enum.IntEnum):
|
|
||||||
"""
|
|
||||||
.. versionadded:: 5.0
|
|
||||||
|
|
||||||
Encodes the valid exit codes by pytest.
|
|
||||||
|
|
||||||
Currently users and plugins may supply other exit codes as well.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#: tests passed
|
|
||||||
OK = 0
|
|
||||||
#: tests failed
|
|
||||||
TESTS_FAILED = 1
|
|
||||||
#: pytest was interrupted
|
|
||||||
INTERRUPTED = 2
|
|
||||||
#: an internal error got in the way
|
|
||||||
INTERNAL_ERROR = 3
|
|
||||||
#: pytest was misused
|
|
||||||
USAGE_ERROR = 4
|
|
||||||
#: pytest couldn't find tests
|
|
||||||
NO_TESTS_COLLECTED = 5
|
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
parser.addini(
|
parser.addini(
|
||||||
"norecursedirs",
|
"norecursedirs",
|
||||||
|
|
|
@ -30,8 +30,8 @@ from _pytest.capture import MultiCapture
|
||||||
from _pytest.capture import SysCapture
|
from _pytest.capture import SysCapture
|
||||||
from _pytest.compat import TYPE_CHECKING
|
from _pytest.compat import TYPE_CHECKING
|
||||||
from _pytest.config import _PluggyPlugin
|
from _pytest.config import _PluggyPlugin
|
||||||
|
from _pytest.config import ExitCode
|
||||||
from _pytest.fixtures import FixtureRequest
|
from _pytest.fixtures import FixtureRequest
|
||||||
from _pytest.main import ExitCode
|
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
from _pytest.monkeypatch import MonkeyPatch
|
from _pytest.monkeypatch import MonkeyPatch
|
||||||
from _pytest.nodes import Collector
|
from _pytest.nodes import Collector
|
||||||
|
|
|
@ -26,7 +26,7 @@ from more_itertools import collapse
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest import nodes
|
from _pytest import nodes
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
from _pytest.reports import CollectReport
|
from _pytest.reports import CollectReport
|
||||||
from _pytest.reports import TestReport
|
from _pytest.reports import TestReport
|
||||||
|
|
|
@ -6,6 +6,7 @@ from _pytest import __version__
|
||||||
from _pytest.assertion import register_assert_rewrite
|
from _pytest.assertion import register_assert_rewrite
|
||||||
from _pytest.compat import _setup_collect_fakemodule
|
from _pytest.compat import _setup_collect_fakemodule
|
||||||
from _pytest.config import cmdline
|
from _pytest.config import cmdline
|
||||||
|
from _pytest.config import ExitCode
|
||||||
from _pytest.config import hookimpl
|
from _pytest.config import hookimpl
|
||||||
from _pytest.config import hookspec
|
from _pytest.config import hookspec
|
||||||
from _pytest.config import main
|
from _pytest.config import main
|
||||||
|
@ -15,7 +16,6 @@ from _pytest.fixtures import fillfixtures as _fillfuncargs
|
||||||
from _pytest.fixtures import fixture
|
from _pytest.fixtures import fixture
|
||||||
from _pytest.fixtures import yield_fixture
|
from _pytest.fixtures import yield_fixture
|
||||||
from _pytest.freeze_support import freeze_includes
|
from _pytest.freeze_support import freeze_includes
|
||||||
from _pytest.main import ExitCode
|
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
from _pytest.mark import MARK_GEN as mark
|
from _pytest.mark import MARK_GEN as mark
|
||||||
from _pytest.mark import param
|
from _pytest.mark import param
|
||||||
|
|
|
@ -8,7 +8,7 @@ import py
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.compat import importlib_metadata
|
from _pytest.compat import importlib_metadata
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
|
||||||
|
|
||||||
def prepend_pythonpath(*dirs):
|
def prepend_pythonpath(*dirs):
|
||||||
|
@ -412,7 +412,7 @@ class TestGeneralUsage:
|
||||||
def test_report_all_failed_collections_initargs(self, testdir):
|
def test_report_all_failed_collections_initargs(self, testdir):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
|
||||||
def pytest_sessionfinish(exitstatus):
|
def pytest_sessionfinish(exitstatus):
|
||||||
assert exitstatus == ExitCode.USAGE_ERROR
|
assert exitstatus == ExitCode.USAGE_ERROR
|
||||||
|
|
|
@ -4,7 +4,7 @@ import textwrap
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.nodes import Collector
|
from _pytest.nodes import Collector
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ from _pytest.assertion.rewrite import get_cache_dir
|
||||||
from _pytest.assertion.rewrite import PYC_TAIL
|
from _pytest.assertion.rewrite import PYC_TAIL
|
||||||
from _pytest.assertion.rewrite import PYTEST_TAG
|
from _pytest.assertion.rewrite import PYTEST_TAG
|
||||||
from _pytest.assertion.rewrite import rewrite_asserts
|
from _pytest.assertion.rewrite import rewrite_asserts
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.pathlib import Path
|
from _pytest.pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import sys
|
||||||
import py
|
import py
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
|
||||||
pytest_plugins = ("pytester",)
|
pytest_plugins = ("pytester",)
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ from typing import TextIO
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest import capture
|
from _pytest import capture
|
||||||
from _pytest.capture import CaptureManager
|
from _pytest.capture import CaptureManager
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
|
||||||
# note: py.io capture tests where copied from
|
# note: py.io capture tests where copied from
|
||||||
# pylib 1.4.20.dev2 (rev 13d9af95547e)
|
# pylib 1.4.20.dev2 (rev 13d9af95547e)
|
||||||
|
|
|
@ -6,8 +6,8 @@ import textwrap
|
||||||
import py
|
import py
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from _pytest.config import ExitCode
|
||||||
from _pytest.main import _in_venv
|
from _pytest.main import _in_venv
|
||||||
from _pytest.main import ExitCode
|
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
from _pytest.pytester import Testdir
|
from _pytest.pytester import Testdir
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,11 @@ import pytest
|
||||||
from _pytest.compat import importlib_metadata
|
from _pytest.compat import importlib_metadata
|
||||||
from _pytest.config import _iter_rewritable_modules
|
from _pytest.config import _iter_rewritable_modules
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
|
from _pytest.config import ExitCode
|
||||||
from _pytest.config.exceptions import UsageError
|
from _pytest.config.exceptions import UsageError
|
||||||
from _pytest.config.findpaths import determine_setup
|
from _pytest.config.findpaths import determine_setup
|
||||||
from _pytest.config.findpaths import get_common_ancestor
|
from _pytest.config.findpaths import get_common_ancestor
|
||||||
from _pytest.config.findpaths import getcfg
|
from _pytest.config.findpaths import getcfg
|
||||||
from _pytest.main import ExitCode
|
|
||||||
from _pytest.pathlib import Path
|
from _pytest.pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
@ -1134,7 +1134,7 @@ class TestOverrideIniArgs:
|
||||||
% (testdir.request.config._parser.optparser.prog,)
|
% (testdir.request.config._parser.optparser.prog,)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
assert result.ret == _pytest.main.ExitCode.USAGE_ERROR
|
assert result.ret == _pytest.config.ExitCode.USAGE_ERROR
|
||||||
|
|
||||||
def test_override_ini_does_not_contain_paths(self, _config_for_test, _sys_snapshot):
|
def test_override_ini_does_not_contain_paths(self, _config_for_test, _sys_snapshot):
|
||||||
"""Check that -o no longer swallows all options after it (#3103)"""
|
"""Check that -o no longer swallows all options after it (#3103)"""
|
||||||
|
|
|
@ -4,8 +4,8 @@ import textwrap
|
||||||
import py
|
import py
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from _pytest.config import ExitCode
|
||||||
from _pytest.config import PytestPluginManager
|
from _pytest.config import PytestPluginManager
|
||||||
from _pytest.main import ExitCode
|
|
||||||
from _pytest.pathlib import Path
|
from _pytest.pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
|
||||||
|
|
||||||
def test_version(testdir, pytestconfig):
|
def test_version(testdir, pytestconfig):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
|
|
@ -3,7 +3,7 @@ import sys
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.mark import EMPTY_PARAMETERSET_OPTION
|
from _pytest.mark import EMPTY_PARAMETERSET_OPTION
|
||||||
from _pytest.mark import MarkGenerator as Mark
|
from _pytest.mark import MarkGenerator as Mark
|
||||||
from _pytest.nodes import Collector
|
from _pytest.nodes import Collector
|
||||||
|
|
|
@ -3,9 +3,9 @@ import sys
|
||||||
import types
|
import types
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from _pytest.config import ExitCode
|
||||||
from _pytest.config import PytestPluginManager
|
from _pytest.config import PytestPluginManager
|
||||||
from _pytest.config.exceptions import UsageError
|
from _pytest.config.exceptions import UsageError
|
||||||
from _pytest.main import ExitCode
|
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ import py.path
|
||||||
|
|
||||||
import _pytest.pytester as pytester
|
import _pytest.pytester as pytester
|
||||||
import pytest
|
import pytest
|
||||||
|
from _pytest.config import ExitCode
|
||||||
from _pytest.config import PytestPluginManager
|
from _pytest.config import PytestPluginManager
|
||||||
from _pytest.main import ExitCode
|
|
||||||
from _pytest.outcomes import Failed
|
from _pytest.outcomes import Failed
|
||||||
from _pytest.pytester import CwdSnapshot
|
from _pytest.pytester import CwdSnapshot
|
||||||
from _pytest.pytester import HookRecorder
|
from _pytest.pytester import HookRecorder
|
||||||
|
|
|
@ -10,10 +10,10 @@ import py
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest import main
|
|
||||||
from _pytest import outcomes
|
from _pytest import outcomes
|
||||||
from _pytest import reports
|
from _pytest import reports
|
||||||
from _pytest import runner
|
from _pytest import runner
|
||||||
|
from _pytest.config import ExitCode
|
||||||
from _pytest.outcomes import Exit
|
from _pytest.outcomes import Exit
|
||||||
from _pytest.outcomes import Failed
|
from _pytest.outcomes import Failed
|
||||||
from _pytest.outcomes import OutcomeException
|
from _pytest.outcomes import OutcomeException
|
||||||
|
@ -681,7 +681,7 @@ def test_pytest_fail_notrace_non_ascii(testdir) -> None:
|
||||||
def test_pytest_no_tests_collected_exit_status(testdir) -> None:
|
def test_pytest_no_tests_collected_exit_status(testdir) -> None:
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
result.stdout.fnmatch_lines(["*collected 0 items*"])
|
result.stdout.fnmatch_lines(["*collected 0 items*"])
|
||||||
assert result.ret == main.ExitCode.NO_TESTS_COLLECTED
|
assert result.ret == ExitCode.NO_TESTS_COLLECTED
|
||||||
|
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
test_foo="""
|
test_foo="""
|
||||||
|
@ -692,12 +692,12 @@ def test_pytest_no_tests_collected_exit_status(testdir) -> None:
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
result.stdout.fnmatch_lines(["*collected 1 item*"])
|
result.stdout.fnmatch_lines(["*collected 1 item*"])
|
||||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||||
assert result.ret == main.ExitCode.OK
|
assert result.ret == ExitCode.OK
|
||||||
|
|
||||||
result = testdir.runpytest("-k nonmatch")
|
result = testdir.runpytest("-k nonmatch")
|
||||||
result.stdout.fnmatch_lines(["*collected 1 item*"])
|
result.stdout.fnmatch_lines(["*collected 1 item*"])
|
||||||
result.stdout.fnmatch_lines(["*1 deselected*"])
|
result.stdout.fnmatch_lines(["*1 deselected*"])
|
||||||
assert result.ret == main.ExitCode.NO_TESTS_COLLECTED
|
assert result.ret == ExitCode.NO_TESTS_COLLECTED
|
||||||
|
|
||||||
|
|
||||||
def test_exception_printing_skip() -> None:
|
def test_exception_printing_skip() -> None:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
|
||||||
|
|
||||||
class SessionTests:
|
class SessionTests:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(params=["--setup-only", "--setup-plan", "--setup-show"], scope="module")
|
@pytest.fixture(params=["--setup-only", "--setup-plan", "--setup-show"], scope="module")
|
||||||
|
|
|
@ -12,7 +12,7 @@ import pluggy
|
||||||
import py
|
import py
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
from _pytest.pytester import Testdir
|
from _pytest.pytester import Testdir
|
||||||
from _pytest.reports import BaseReport
|
from _pytest.reports import BaseReport
|
||||||
from _pytest.terminal import _folded_skips
|
from _pytest.terminal import _folded_skips
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import gc
|
import gc
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.main import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
|
||||||
|
|
||||||
def test_simple_unittest(testdir):
|
def test_simple_unittest(testdir):
|
||||||
|
|
Loading…
Reference in New Issue