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:
Ran Benita 2020-02-10 23:43:30 +02:00
parent 1ebca37689
commit d33da078a8
25 changed files with 54 additions and 55 deletions

View File

@ -738,7 +738,7 @@ ExceptionInfo
pytest.ExitCode
~~~~~~~~~~~~~~~
.. autoclass:: _pytest.main.ExitCode
.. autoclass:: _pytest.config.ExitCode
:members:

View File

@ -33,7 +33,7 @@ Running ``pytest`` can result in six different exit codes:
:Exit code 4: pytest command line usage error
: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

View File

@ -1,6 +1,7 @@
""" command line options, ini-file and conftest.py processing. """
import argparse
import copy
import enum
import inspect
import os
import shlex
@ -61,6 +62,29 @@ hookimpl = HookimplMarker("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):
def __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]
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.
: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
initialization.
"""
from _pytest.main import ExitCode
try:
try:
config = _prepareconfig(args, plugins)

View File

@ -1,5 +1,4 @@
""" core implementation of testing process: init, session, runtest loop. """
import enum
import fnmatch
import functools
import importlib
@ -21,6 +20,7 @@ from _pytest import nodes
from _pytest.compat import TYPE_CHECKING
from _pytest.config import Config
from _pytest.config import directory_arg
from _pytest.config import ExitCode
from _pytest.config import hookimpl
from _pytest.config import UsageError
from _pytest.fixtures import FixtureManager
@ -36,29 +36,6 @@ if TYPE_CHECKING:
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):
parser.addini(
"norecursedirs",

View File

@ -30,8 +30,8 @@ from _pytest.capture import MultiCapture
from _pytest.capture import SysCapture
from _pytest.compat import TYPE_CHECKING
from _pytest.config import _PluggyPlugin
from _pytest.config import ExitCode
from _pytest.fixtures import FixtureRequest
from _pytest.main import ExitCode
from _pytest.main import Session
from _pytest.monkeypatch import MonkeyPatch
from _pytest.nodes import Collector

View File

@ -26,7 +26,7 @@ from more_itertools import collapse
import pytest
from _pytest import nodes
from _pytest.config import Config
from _pytest.main import ExitCode
from _pytest.config import ExitCode
from _pytest.main import Session
from _pytest.reports import CollectReport
from _pytest.reports import TestReport

View File

@ -6,6 +6,7 @@ from _pytest import __version__
from _pytest.assertion import register_assert_rewrite
from _pytest.compat import _setup_collect_fakemodule
from _pytest.config import cmdline
from _pytest.config import ExitCode
from _pytest.config import hookimpl
from _pytest.config import hookspec
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 yield_fixture
from _pytest.freeze_support import freeze_includes
from _pytest.main import ExitCode
from _pytest.main import Session
from _pytest.mark import MARK_GEN as mark
from _pytest.mark import param

View File

@ -8,7 +8,7 @@ import py
import pytest
from _pytest.compat import importlib_metadata
from _pytest.main import ExitCode
from _pytest.config import ExitCode
def prepend_pythonpath(*dirs):
@ -412,7 +412,7 @@ class TestGeneralUsage:
def test_report_all_failed_collections_initargs(self, testdir):
testdir.makeconftest(
"""
from _pytest.main import ExitCode
from _pytest.config import ExitCode
def pytest_sessionfinish(exitstatus):
assert exitstatus == ExitCode.USAGE_ERROR

View File

@ -4,7 +4,7 @@ import textwrap
import _pytest._code
import pytest
from _pytest.main import ExitCode
from _pytest.config import ExitCode
from _pytest.nodes import Collector

View File

@ -21,7 +21,7 @@ from _pytest.assertion.rewrite import get_cache_dir
from _pytest.assertion.rewrite import PYC_TAIL
from _pytest.assertion.rewrite import PYTEST_TAG
from _pytest.assertion.rewrite import rewrite_asserts
from _pytest.main import ExitCode
from _pytest.config import ExitCode
from _pytest.pathlib import Path

View File

@ -6,7 +6,7 @@ import sys
import py
import pytest
from _pytest.main import ExitCode
from _pytest.config import ExitCode
pytest_plugins = ("pytester",)

View File

@ -15,7 +15,7 @@ from typing import TextIO
import pytest
from _pytest import capture
from _pytest.capture import CaptureManager
from _pytest.main import ExitCode
from _pytest.config import ExitCode
# note: py.io capture tests where copied from
# pylib 1.4.20.dev2 (rev 13d9af95547e)

View File

@ -6,8 +6,8 @@ import textwrap
import py
import pytest
from _pytest.config import ExitCode
from _pytest.main import _in_venv
from _pytest.main import ExitCode
from _pytest.main import Session
from _pytest.pytester import Testdir

View File

@ -7,11 +7,11 @@ import pytest
from _pytest.compat import importlib_metadata
from _pytest.config import _iter_rewritable_modules
from _pytest.config import Config
from _pytest.config import ExitCode
from _pytest.config.exceptions import UsageError
from _pytest.config.findpaths import determine_setup
from _pytest.config.findpaths import get_common_ancestor
from _pytest.config.findpaths import getcfg
from _pytest.main import ExitCode
from _pytest.pathlib import Path
@ -1134,7 +1134,7 @@ class TestOverrideIniArgs:
% (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):
"""Check that -o no longer swallows all options after it (#3103)"""

View File

@ -4,8 +4,8 @@ import textwrap
import py
import pytest
from _pytest.config import ExitCode
from _pytest.config import PytestPluginManager
from _pytest.main import ExitCode
from _pytest.pathlib import Path

View File

@ -1,5 +1,5 @@
import pytest
from _pytest.main import ExitCode
from _pytest.config import ExitCode
def test_version(testdir, pytestconfig):

View File

@ -1,5 +1,5 @@
import pytest
from _pytest.main import ExitCode
from _pytest.config import ExitCode
@pytest.mark.parametrize(

View File

@ -3,7 +3,7 @@ import sys
from unittest import mock
import pytest
from _pytest.main import ExitCode
from _pytest.config import ExitCode
from _pytest.mark import EMPTY_PARAMETERSET_OPTION
from _pytest.mark import MarkGenerator as Mark
from _pytest.nodes import Collector

View File

@ -3,9 +3,9 @@ import sys
import types
import pytest
from _pytest.config import ExitCode
from _pytest.config import PytestPluginManager
from _pytest.config.exceptions import UsageError
from _pytest.main import ExitCode
from _pytest.main import Session

View File

@ -8,8 +8,8 @@ import py.path
import _pytest.pytester as pytester
import pytest
from _pytest.config import ExitCode
from _pytest.config import PytestPluginManager
from _pytest.main import ExitCode
from _pytest.outcomes import Failed
from _pytest.pytester import CwdSnapshot
from _pytest.pytester import HookRecorder

View File

@ -10,10 +10,10 @@ import py
import _pytest._code
import pytest
from _pytest import main
from _pytest import outcomes
from _pytest import reports
from _pytest import runner
from _pytest.config import ExitCode
from _pytest.outcomes import Exit
from _pytest.outcomes import Failed
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:
result = testdir.runpytest()
result.stdout.fnmatch_lines(["*collected 0 items*"])
assert result.ret == main.ExitCode.NO_TESTS_COLLECTED
assert result.ret == ExitCode.NO_TESTS_COLLECTED
testdir.makepyfile(
test_foo="""
@ -692,12 +692,12 @@ def test_pytest_no_tests_collected_exit_status(testdir) -> None:
result = testdir.runpytest()
result.stdout.fnmatch_lines(["*collected 1 item*"])
result.stdout.fnmatch_lines(["*1 passed*"])
assert result.ret == main.ExitCode.OK
assert result.ret == ExitCode.OK
result = testdir.runpytest("-k nonmatch")
result.stdout.fnmatch_lines(["*collected 1 item*"])
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:

View File

@ -1,5 +1,5 @@
import pytest
from _pytest.main import ExitCode
from _pytest.config import ExitCode
class SessionTests:

View File

@ -1,5 +1,5 @@
import pytest
from _pytest.main import ExitCode
from _pytest.config import ExitCode
@pytest.fixture(params=["--setup-only", "--setup-plan", "--setup-show"], scope="module")

View File

@ -12,7 +12,7 @@ import pluggy
import py
import pytest
from _pytest.main import ExitCode
from _pytest.config import ExitCode
from _pytest.pytester import Testdir
from _pytest.reports import BaseReport
from _pytest.terminal import _folded_skips

View File

@ -1,7 +1,7 @@
import gc
import pytest
from _pytest.main import ExitCode
from _pytest.config import ExitCode
def test_simple_unittest(testdir):