-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
conversion of exit codes to enum + exposure #5420
Changes from 2 commits
2b92fee
2bd619e
065fa17
103d614
8b3b10b
1cfea5f
ab6ed38
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Introduce the ``pytest.ExitCode`` Enum and make session.exitcode an instance of it. | ||
User defined exit codes are still valid, but consumers need to take the enum into account. | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
""" core implementation of testing process: init, session, runtest loop. """ | ||
import enum | ||
import fnmatch | ||
import functools | ||
import os | ||
|
@@ -19,12 +20,15 @@ | |
from _pytest.runner import collect_one_node | ||
|
||
# exitcodes for the command line | ||
EXIT_OK = 0 | ||
EXIT_TESTSFAILED = 1 | ||
EXIT_INTERRUPTED = 2 | ||
EXIT_INTERNALERROR = 3 | ||
EXIT_USAGEERROR = 4 | ||
EXIT_NOTESTSCOLLECTED = 5 | ||
|
||
|
||
class ExitCode(enum.IntEnum): | ||
RonnyPfannschmidt marked this conversation as resolved.
Show resolved
Hide resolved
|
||
OK = 0 | ||
TESTS_FAILED = 1 | ||
INTERRUPTED = 2 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just occurred to me: is there a consensus about how to name the enumerate members? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm all examples in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. using PEP8 for constants There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. basically enum members are constants, thus follow the same rules as constants ^^ |
||
INTERNAL_ERROR = 3 | ||
USAGE_ERROR = 4 | ||
NO_TESTS_COLLECTED = 5 | ||
|
||
|
||
def pytest_addoption(parser): | ||
|
@@ -188,7 +192,7 @@ def pytest_configure(config): | |
def wrap_session(config, doit): | ||
"""Skeleton command line program""" | ||
session = Session(config) | ||
session.exitstatus = EXIT_OK | ||
session.exitstatus = ExitCode.OK | ||
initstate = 0 | ||
try: | ||
try: | ||
|
@@ -198,13 +202,13 @@ def wrap_session(config, doit): | |
initstate = 2 | ||
session.exitstatus = doit(config, session) or 0 | ||
except UsageError: | ||
session.exitstatus = EXIT_USAGEERROR | ||
session.exitstatus = ExitCode.USAGE_ERROR | ||
raise | ||
except Failed: | ||
session.exitstatus = EXIT_TESTSFAILED | ||
session.exitstatus = ExitCode.TESTS_FAILED | ||
except (KeyboardInterrupt, exit.Exception): | ||
excinfo = _pytest._code.ExceptionInfo.from_current() | ||
exitstatus = EXIT_INTERRUPTED | ||
exitstatus = ExitCode.INTERRUPTED | ||
if isinstance(excinfo.value, exit.Exception): | ||
if excinfo.value.returncode is not None: | ||
exitstatus = excinfo.value.returncode | ||
|
@@ -217,7 +221,7 @@ def wrap_session(config, doit): | |
except: # noqa | ||
excinfo = _pytest._code.ExceptionInfo.from_current() | ||
config.notify_exception(excinfo, config.option) | ||
session.exitstatus = EXIT_INTERNALERROR | ||
session.exitstatus = ExitCode.INTERNAL_ERROR | ||
if excinfo.errisinstance(SystemExit): | ||
sys.stderr.write("mainloop: caught unexpected SystemExit!\n") | ||
|
||
|
@@ -243,9 +247,9 @@ def _main(config, session): | |
config.hook.pytest_runtestloop(session=session) | ||
|
||
if session.testsfailed: | ||
return EXIT_TESTSFAILED | ||
return ExitCode.TESTS_FAILED | ||
elif session.testscollected == 0: | ||
return EXIT_NOTESTSCOLLECTED | ||
return ExitCode.NO_TESTS_COLLECTED | ||
|
||
|
||
def pytest_collection(session): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,8 +19,7 @@ | |
from _pytest.assertion.rewrite import AssertionRewritingHook | ||
from _pytest.capture import MultiCapture | ||
from _pytest.capture import SysCapture | ||
from _pytest.main import EXIT_INTERRUPTED | ||
from _pytest.main import EXIT_OK | ||
from _pytest.main import ExitCode | ||
from _pytest.main import Session | ||
from _pytest.monkeypatch import MonkeyPatch | ||
from _pytest.pathlib import Path | ||
|
@@ -691,7 +690,7 @@ def getnode(self, config, arg): | |
p = py.path.local(arg) | ||
config.hook.pytest_sessionstart(session=session) | ||
res = session.perform_collect([str(p)], genitems=False)[0] | ||
config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK) | ||
config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK) | ||
return res | ||
|
||
def getpathnode(self, path): | ||
|
@@ -708,11 +707,11 @@ def getpathnode(self, path): | |
x = session.fspath.bestrelpath(path) | ||
config.hook.pytest_sessionstart(session=session) | ||
res = session.perform_collect([x], genitems=False)[0] | ||
config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK) | ||
config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK) | ||
return res | ||
|
||
def genitems(self, colitems): | ||
"""Generate all test items from a collection node. | ||
"""Generate all test items from a collection node.src/_pytest/main.py | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. paste error? |
||
|
||
This recurses into the collection node and returns a list of all the | ||
test items contained within. | ||
|
@@ -841,7 +840,7 @@ class reprec: | |
|
||
# typically we reraise keyboard interrupts from the child run | ||
# because it's our user requesting interruption of the testing | ||
if ret == EXIT_INTERRUPTED and not no_reraise_ctrlc: | ||
if ret == ExitCode.INTERRUPTED and not no_reraise_ctrlc: | ||
calls = reprec.getcalls("pytest_keyboard_interrupt") | ||
if calls and calls[-1].excinfo.type == KeyboardInterrupt: | ||
raise KeyboardInterrupt() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"but consumers need to take the enum into account."
Not clear to me what this means, what consumers would need to do specifically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
users of that api, like the xdist release you just made to support it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh OK, I got confused because I thought the first and second sentence were related, but the "but consumers take the enum into account" phrase was actually referring to the "Introduce the pytestExitCode" phase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about:
(can't use the "suggestion" feature as this spams multiple lines)