5
5
import importlib
6
6
import os
7
7
import sys
8
+ from typing import Callable
8
9
from typing import Dict
9
10
from typing import FrozenSet
10
11
from typing import List
23
24
from _pytest .config import UsageError
24
25
from _pytest .fixtures import FixtureManager
25
26
from _pytest .nodes import Node
26
- from _pytest .outcomes import exit
27
+ from _pytest .outcomes import Exit
27
28
from _pytest .runner import collect_one_node
28
29
from _pytest .runner import SetupState
29
30
@@ -194,7 +195,9 @@ def pytest_addoption(parser):
194
195
)
195
196
196
197
197
- def wrap_session (config , doit ):
198
+ def wrap_session (
199
+ config : Config , doit : Callable [[Config , "Session" ], Optional [Union [int , ExitCode ]]]
200
+ ) -> Union [int , ExitCode ]:
198
201
"""Skeleton command line program"""
199
202
session = Session (config )
200
203
session .exitstatus = ExitCode .OK
@@ -211,10 +214,10 @@ def wrap_session(config, doit):
211
214
raise
212
215
except Failed :
213
216
session .exitstatus = ExitCode .TESTS_FAILED
214
- except (KeyboardInterrupt , exit . Exception ):
217
+ except (KeyboardInterrupt , Exit ):
215
218
excinfo = _pytest ._code .ExceptionInfo .from_current ()
216
- exitstatus = ExitCode .INTERRUPTED
217
- if isinstance (excinfo .value , exit . Exception ):
219
+ exitstatus = ExitCode .INTERRUPTED # type: Union[int, ExitCode]
220
+ if isinstance (excinfo .value , Exit ):
218
221
if excinfo .value .returncode is not None :
219
222
exitstatus = excinfo .value .returncode
220
223
if initstate < 2 :
@@ -228,7 +231,7 @@ def wrap_session(config, doit):
228
231
excinfo = _pytest ._code .ExceptionInfo .from_current ()
229
232
try :
230
233
config .notify_exception (excinfo , config .option )
231
- except exit . Exception as exc :
234
+ except Exit as exc :
232
235
if exc .returncode is not None :
233
236
session .exitstatus = exc .returncode
234
237
sys .stderr .write ("{}: {}\n " .format (type (exc ).__name__ , exc ))
@@ -237,12 +240,18 @@ def wrap_session(config, doit):
237
240
sys .stderr .write ("mainloop: caught unexpected SystemExit!\n " )
238
241
239
242
finally :
240
- excinfo = None # Explicitly break reference cycle.
243
+ # Explicitly break reference cycle.
244
+ excinfo = None # type: ignore
241
245
session .startdir .chdir ()
242
246
if initstate >= 2 :
243
- config .hook .pytest_sessionfinish (
244
- session = session , exitstatus = session .exitstatus
245
- )
247
+ try :
248
+ config .hook .pytest_sessionfinish (
249
+ session = session , exitstatus = session .exitstatus
250
+ )
251
+ except Exit as exc :
252
+ if exc .returncode is not None :
253
+ session .exitstatus = exc .returncode
254
+ sys .stderr .write ("{}: {}\n " .format (type (exc ).__name__ , exc ))
246
255
config ._ensure_unconfigure ()
247
256
return session .exitstatus
248
257
@@ -382,6 +391,7 @@ class Session(nodes.FSCollector):
382
391
_setupstate = None # type: SetupState
383
392
# Set on the session by fixtures.pytest_sessionstart.
384
393
_fixturemanager = None # type: FixtureManager
394
+ exitstatus = None # type: Union[int, ExitCode]
385
395
386
396
def __init__ (self , config : Config ) -> None :
387
397
nodes .FSCollector .__init__ (
0 commit comments