Skip to content

Commit 94b4ead

Browse files
initial conversion of exit codes to enum
1 parent 042a10f commit 94b4ead

19 files changed

+86
-91
lines changed

src/_pytest/config/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def main(args=None, plugins=None):
4949
:arg plugins: list of plugin objects to be auto-registered during
5050
initialization.
5151
"""
52-
from _pytest.main import EXIT_USAGEERROR
52+
from _pytest.main import ExitCode
5353

5454
try:
5555
try:
@@ -79,7 +79,7 @@ def main(args=None, plugins=None):
7979
tw = py.io.TerminalWriter(sys.stderr)
8080
for msg in e.args:
8181
tw.line("ERROR: {}\n".format(msg), red=True)
82-
return EXIT_USAGEERROR
82+
return ExitCode.USAGE_ERROR
8383

8484

8585
class cmdline: # compatibility namespace

src/_pytest/main.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
""" core implementation of testing process: init, session, runtest loop. """
22
import fnmatch
3+
import enum
34
import functools
45
import os
56
import pkgutil
@@ -19,12 +20,15 @@
1920
from _pytest.runner import collect_one_node
2021

2122
# exitcodes for the command line
22-
EXIT_OK = 0
23-
EXIT_TESTSFAILED = 1
24-
EXIT_INTERRUPTED = 2
25-
EXIT_INTERNALERROR = 3
26-
EXIT_USAGEERROR = 4
27-
EXIT_NOTESTSCOLLECTED = 5
23+
24+
25+
class ExitCode(enum.IntEnum):
26+
OK = 0
27+
TESTS_FAILED = 1
28+
INTERRUPTED = 2
29+
INTERNAL_ERROR = 3
30+
USAGE_ERROR = 4
31+
NO_TESTS_COLLECTED = 5
2832

2933

3034
def pytest_addoption(parser):
@@ -188,7 +192,7 @@ def pytest_configure(config):
188192
def wrap_session(config, doit):
189193
"""Skeleton command line program"""
190194
session = Session(config)
191-
session.exitstatus = EXIT_OK
195+
session.exitstatus = ExitCode.OK
192196
initstate = 0
193197
try:
194198
try:
@@ -201,10 +205,10 @@ def wrap_session(config, doit):
201205
session.exitstatus = EXIT_USAGEERROR
202206
raise
203207
except Failed:
204-
session.exitstatus = EXIT_TESTSFAILED
208+
session.exitstatus = ExitCode.TESTS_FAILED
205209
except (KeyboardInterrupt, exit.Exception):
206210
excinfo = _pytest._code.ExceptionInfo.from_current()
207-
exitstatus = EXIT_INTERRUPTED
211+
exitstatus = ExitCode.INTERRUPTED
208212
if isinstance(excinfo.value, exit.Exception):
209213
if excinfo.value.returncode is not None:
210214
exitstatus = excinfo.value.returncode
@@ -217,7 +221,7 @@ def wrap_session(config, doit):
217221
except: # noqa
218222
excinfo = _pytest._code.ExceptionInfo.from_current()
219223
config.notify_exception(excinfo, config.option)
220-
session.exitstatus = EXIT_INTERNALERROR
224+
session.exitstatus = ExitCode.INTERNAL_ERROR
221225
if excinfo.errisinstance(SystemExit):
222226
sys.stderr.write("mainloop: caught unexpected SystemExit!\n")
223227

@@ -243,9 +247,9 @@ def _main(config, session):
243247
config.hook.pytest_runtestloop(session=session)
244248

245249
if session.testsfailed:
246-
return EXIT_TESTSFAILED
250+
return ExitCode.TESTS_FAILED
247251
elif session.testscollected == 0:
248-
return EXIT_NOTESTSCOLLECTED
252+
return ExitCode.NO_TESTS_COLLECTED
249253

250254

251255
def pytest_collection(session):

src/_pytest/pytester.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
from _pytest.assertion.rewrite import AssertionRewritingHook
2020
from _pytest.capture import MultiCapture
2121
from _pytest.capture import SysCapture
22-
from _pytest.main import EXIT_INTERRUPTED
23-
from _pytest.main import EXIT_OK
22+
from _pytest.main import ExitCode
2423
from _pytest.main import Session
2524
from _pytest.monkeypatch import MonkeyPatch
2625
from _pytest.pathlib import Path
@@ -691,7 +690,7 @@ def getnode(self, config, arg):
691690
p = py.path.local(arg)
692691
config.hook.pytest_sessionstart(session=session)
693692
res = session.perform_collect([str(p)], genitems=False)[0]
694-
config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK)
693+
config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK)
695694
return res
696695

697696
def getpathnode(self, path):
@@ -708,11 +707,11 @@ def getpathnode(self, path):
708707
x = session.fspath.bestrelpath(path)
709708
config.hook.pytest_sessionstart(session=session)
710709
res = session.perform_collect([x], genitems=False)[0]
711-
config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK)
710+
config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK)
712711
return res
713712

714713
def genitems(self, colitems):
715-
"""Generate all test items from a collection node.
714+
"""Generate all test items from a collection node.src/_pytest/main.py
716715
717716
This recurses into the collection node and returns a list of all the
718717
test items contained within.
@@ -841,7 +840,7 @@ class reprec:
841840

842841
# typically we reraise keyboard interrupts from the child run
843842
# because it's our user requesting interruption of the testing
844-
if ret == EXIT_INTERRUPTED and not no_reraise_ctrlc:
843+
if ret == ExitCode.INTERRUPTED and not no_reraise_ctrlc:
845844
calls = reprec.getcalls("pytest_keyboard_interrupt")
846845
if calls and calls[-1].excinfo.type == KeyboardInterrupt:
847846
raise KeyboardInterrupt()

src/_pytest/terminal.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,7 @@
1616

1717
import pytest
1818
from _pytest import nodes
19-
from _pytest.main import EXIT_INTERRUPTED
20-
from _pytest.main import EXIT_NOTESTSCOLLECTED
21-
from _pytest.main import EXIT_OK
22-
from _pytest.main import EXIT_TESTSFAILED
23-
from _pytest.main import EXIT_USAGEERROR
19+
from _pytest.main import ExitCode
2420

2521
REPORT_COLLECTING_RESOLUTION = 0.5
2622

@@ -654,17 +650,17 @@ def pytest_sessionfinish(self, exitstatus):
654650
outcome.get_result()
655651
self._tw.line("")
656652
summary_exit_codes = (
657-
EXIT_OK,
658-
EXIT_TESTSFAILED,
659-
EXIT_INTERRUPTED,
660-
EXIT_USAGEERROR,
661-
EXIT_NOTESTSCOLLECTED,
653+
ExitCode.OK,
654+
ExitCode.TESTS_FAILED,
655+
ExitCode.INTERRUPTED,
656+
ExitCode.USAGE_ERROR,
657+
ExitCode.NO_TESTS_COLLECTED,
662658
)
663659
if exitstatus in summary_exit_codes:
664660
self.config.hook.pytest_terminal_summary(
665661
terminalreporter=self, exitstatus=exitstatus, config=self.config
666662
)
667-
if exitstatus == EXIT_INTERRUPTED:
663+
if exitstatus == ExitCode.INTERRUPTED:
668664
self._report_keyboardinterrupt()
669665
del self._keyboardinterrupt_memo
670666
self.summary_stats()

src/pytest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from _pytest.fixtures import fixture
1616
from _pytest.fixtures import yield_fixture
1717
from _pytest.freeze_support import freeze_includes
18+
from _pytest.main import ExitCode
1819
from _pytest.main import Session
1920
from _pytest.mark import MARK_GEN as mark
2021
from _pytest.mark import param
@@ -57,6 +58,7 @@
5758
"Collector",
5859
"deprecated_call",
5960
"exit",
61+
"ExitCode",
6062
"fail",
6163
"File",
6264
"fixture",

testing/acceptance_test.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
import py
99

1010
import pytest
11-
from _pytest.main import EXIT_NOTESTSCOLLECTED
12-
from _pytest.main import EXIT_USAGEERROR
11+
from _pytest.main import ExitCode
1312
from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG
1413

1514

@@ -24,7 +23,7 @@ class TestGeneralUsage:
2423
def test_config_error(self, testdir):
2524
testdir.copy_example("conftest_usageerror/conftest.py")
2625
result = testdir.runpytest(testdir.tmpdir)
27-
assert result.ret == EXIT_USAGEERROR
26+
assert result.ret == ExitCode.USAGE_ERROR
2827
result.stderr.fnmatch_lines(["*ERROR: hello"])
2928
result.stdout.fnmatch_lines(["*pytest_unconfigure_called"])
3029

@@ -83,7 +82,7 @@ def pytest_unconfigure():
8382
"""
8483
)
8584
result = testdir.runpytest("-s", "asd")
86-
assert result.ret == 4 # EXIT_USAGEERROR
85+
assert result.ret == ExitCode.USAGE_ERROR
8786
result.stderr.fnmatch_lines(["ERROR: file not found*asd"])
8887
result.stdout.fnmatch_lines(["*---configure", "*---unconfigure"])
8988

@@ -229,7 +228,7 @@ def pytest_collect_directory():
229228
"""
230229
)
231230
result = testdir.runpytest()
232-
assert result.ret == EXIT_NOTESTSCOLLECTED
231+
assert result.ret == ExitCode.NO_TESTS_COLLECTED
233232
result.stdout.fnmatch_lines(["*1 skip*"])
234233

235234
def test_issue88_initial_file_multinodes(self, testdir):
@@ -247,7 +246,7 @@ def test_issue93_initialnode_importing_capturing(self, testdir):
247246
"""
248247
)
249248
result = testdir.runpytest()
250-
assert result.ret == EXIT_NOTESTSCOLLECTED
249+
assert result.ret == ExitCode.NO_TESTS_COLLECTED
251250
assert "should not be seen" not in result.stdout.str()
252251
assert "stderr42" not in result.stderr.str()
253252

@@ -290,13 +289,13 @@ def test_issue109_sibling_conftests_not_loaded(self, testdir):
290289
sub2 = testdir.mkdir("sub2")
291290
sub1.join("conftest.py").write("assert 0")
292291
result = testdir.runpytest(sub2)
293-
assert result.ret == EXIT_NOTESTSCOLLECTED
292+
assert result.ret == ExitCode.NO_TESTS_COLLECTED
294293
sub2.ensure("__init__.py")
295294
p = sub2.ensure("test_hello.py")
296295
result = testdir.runpytest(p)
297-
assert result.ret == EXIT_NOTESTSCOLLECTED
296+
assert result.ret == ExitCode.NO_TESTS_COLLECTED
298297
result = testdir.runpytest(sub1)
299-
assert result.ret == EXIT_USAGEERROR
298+
assert result.ret == ExitCode.USAGE_ERROR
300299

301300
def test_directory_skipped(self, testdir):
302301
testdir.makeconftest(
@@ -308,7 +307,7 @@ def pytest_ignore_collect():
308307
)
309308
testdir.makepyfile("def test_hello(): pass")
310309
result = testdir.runpytest()
311-
assert result.ret == EXIT_NOTESTSCOLLECTED
310+
assert result.ret == ExitCode.NO_TESTS_COLLECTED
312311
result.stdout.fnmatch_lines(["*1 skipped*"])
313312

314313
def test_multiple_items_per_collector_byid(self, testdir):
@@ -612,7 +611,7 @@ def test_invoke_with_invalid_type(self, capsys):
612611

613612
def test_invoke_with_path(self, tmpdir, capsys):
614613
retcode = pytest.main(tmpdir)
615-
assert retcode == EXIT_NOTESTSCOLLECTED
614+
assert retcode == ExitCode.NO_TESTS_COLLECTED
616615
out, err = capsys.readouterr()
617616

618617
def test_invoke_plugin_api(self, testdir, capsys):
@@ -1160,7 +1159,7 @@ def test_fixture_mock_integration(testdir):
11601159

11611160
def test_usage_error_code(testdir):
11621161
result = testdir.runpytest("-unknown-option-")
1163-
assert result.ret == EXIT_USAGEERROR
1162+
assert result.ret == ExitCode.USAGE_ERROR
11641163

11651164

11661165
@pytest.mark.filterwarnings("default")

testing/python/collect.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import _pytest._code
66
import pytest
7-
from _pytest.main import EXIT_NOTESTSCOLLECTED
7+
from _pytest.main import ExitCode
88
from _pytest.nodes import Collector
99

1010

@@ -246,7 +246,7 @@ def prop(self):
246246
"""
247247
)
248248
result = testdir.runpytest()
249-
assert result.ret == EXIT_NOTESTSCOLLECTED
249+
assert result.ret == ExitCode.NO_TESTS_COLLECTED
250250

251251

252252
class TestFunction:
@@ -1140,7 +1140,7 @@ class Test(object):
11401140
)
11411141
result = testdir.runpytest()
11421142
assert "TypeError" not in result.stdout.str()
1143-
assert result.ret == EXIT_NOTESTSCOLLECTED
1143+
assert result.ret == ExitCode.NO_TESTS_COLLECTED
11441144

11451145

11461146
def test_collect_functools_partial(testdir):

testing/test_assertrewrite.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from _pytest.assertion.rewrite import AssertionRewritingHook
1616
from _pytest.assertion.rewrite import PYTEST_TAG
1717
from _pytest.assertion.rewrite import rewrite_asserts
18-
from _pytest.main import EXIT_NOTESTSCOLLECTED
18+
from _pytest.main import ExitCode
1919

2020

2121
def setup_module(mod):
@@ -692,7 +692,7 @@ def test_zipfile(self, testdir):
692692
import test_gum.test_lizard"""
693693
% (z_fn,)
694694
)
695-
assert testdir.runpytest().ret == EXIT_NOTESTSCOLLECTED
695+
assert testdir.runpytest().ret == ExitCode.NO_TESTS_COLLECTED
696696

697697
def test_readonly(self, testdir):
698698
sub = testdir.mkdir("testing")
@@ -792,7 +792,7 @@ def test_package_without__init__py(self, testdir):
792792
pkg = testdir.mkdir("a_package_without_init_py")
793793
pkg.join("module.py").ensure()
794794
testdir.makepyfile("import a_package_without_init_py.module")
795-
assert testdir.runpytest().ret == EXIT_NOTESTSCOLLECTED
795+
assert testdir.runpytest().ret == ExitCode.NO_TESTS_COLLECTED
796796

797797
def test_rewrite_warning(self, testdir):
798798
testdir.makeconftest(

testing/test_capture.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import pytest
1313
from _pytest import capture
1414
from _pytest.capture import CaptureManager
15-
from _pytest.main import EXIT_NOTESTSCOLLECTED
15+
from _pytest.main import ExitCode
1616

1717
# note: py.io capture tests where copied from
1818
# pylib 1.4.20.dev2 (rev 13d9af95547e)
@@ -361,7 +361,7 @@ def test_conftestlogging_is_shown(self, testdir):
361361
)
362362
# make sure that logging is still captured in tests
363363
result = testdir.runpytest_subprocess("-s", "-p", "no:capturelog")
364-
assert result.ret == EXIT_NOTESTSCOLLECTED
364+
assert result.ret == ExitCode.NO_TESTS_COLLECTED
365365
result.stderr.fnmatch_lines(["WARNING*hello435*"])
366366
assert "operation on closed file" not in result.stderr.str()
367367

testing/test_collection.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77

88
import pytest
99
from _pytest.main import _in_venv
10-
from _pytest.main import EXIT_INTERRUPTED
11-
from _pytest.main import EXIT_NOTESTSCOLLECTED
10+
from _pytest.main import ExitCode
1211
from _pytest.main import Session
1312

1413

@@ -347,7 +346,7 @@ def pytest_ignore_collect(path, config):
347346
assert result.ret == 0
348347
result.stdout.fnmatch_lines(["*1 passed*"])
349348
result = testdir.runpytest()
350-
assert result.ret == EXIT_NOTESTSCOLLECTED
349+
assert result.ret == ExitCode.NO_TESTS_COLLECTED
351350
result.stdout.fnmatch_lines(["*collected 0 items*"])
352351

353352
def test_collectignore_exclude_on_option(self, testdir):
@@ -364,7 +363,7 @@ def pytest_configure(config):
364363
testdir.mkdir("hello")
365364
testdir.makepyfile(test_world="def test_hello(): pass")
366365
result = testdir.runpytest()
367-
assert result.ret == EXIT_NOTESTSCOLLECTED
366+
assert result.ret == ExitCode.NO_TESTS_COLLECTED
368367
assert "passed" not in result.stdout.str()
369368
result = testdir.runpytest("--XX")
370369
assert result.ret == 0

0 commit comments

Comments
 (0)