Skip to content

Commit 0cc694d

Browse files
authored
Switch away from sys.exit(error_msg) in dmypy (#5982)
This kills a couple birds with one stone: 1. It fixes an interaction with the new run_dmypy api where that message winds up as the return code instead of in stderr. This additionally fixes a type unsoundness/mypy_mypyc crash caused by SystemExit.code being typed as int. 2. It allows us to standardize the irregular exit codes of dmypy as 2.
1 parent 18d4325 commit 0cc694d

File tree

2 files changed

+22
-17
lines changed

2 files changed

+22
-17
lines changed

mypy/dmypy.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,19 @@ def main(argv: List[str]) -> None:
124124
try:
125125
args.action(args)
126126
except BadStatus as err:
127-
sys.exit(err.args[0])
127+
fail(err.args[0])
128128
except Exception:
129129
# We do this explicitly to avoid exceptions percolating up
130130
# through mypy.api invocations
131131
traceback.print_exc()
132132
sys.exit(2)
133133

134134

135+
def fail(msg: str) -> None:
136+
print(msg, file=sys.stderr)
137+
sys.exit(2)
138+
139+
135140
ActionFunction = Callable[[argparse.Namespace], None]
136141

137142

@@ -163,7 +168,7 @@ def do_start(args: argparse.Namespace) -> None:
163168
# Bad or missing status file or dead process; good to start.
164169
pass
165170
else:
166-
sys.exit("Daemon is still alive")
171+
fail("Daemon is still alive")
167172
start_server(args)
168173

169174

@@ -193,7 +198,7 @@ def start_server(args: argparse.Namespace, allow_sources: bool = False) -> None:
193198
from mypy.dmypy_server import daemonize, process_start_options
194199
start_options = process_start_options(args.flags, allow_sources)
195200
if daemonize(start_options, timeout=args.timeout, log_file=args.log_file):
196-
sys.exit(1)
201+
sys.exit(2)
197202
wait_for_server()
198203

199204

@@ -214,7 +219,7 @@ def wait_for_server(timeout: float = 5.0) -> None:
214219
check_status(data)
215220
print("Daemon started")
216221
return
217-
sys.exit("Timed out waiting for daemon to start")
222+
fail("Timed out waiting for daemon to start")
218223

219224

220225
@action(run_parser)
@@ -263,7 +268,7 @@ def do_status(args: argparse.Namespace) -> None:
263268
if args.verbose or 'error' in response:
264269
show_stats(response)
265270
if 'error' in response:
266-
sys.exit("Daemon is stuck; consider %s kill" % sys.argv[0])
271+
fail("Daemon is stuck; consider %s kill" % sys.argv[0])
267272
print("Daemon is up and running")
268273

269274

@@ -274,7 +279,7 @@ def do_stop(args: argparse.Namespace) -> None:
274279
response = request('stop', timeout=5)
275280
if response:
276281
show_stats(response)
277-
sys.exit("Daemon is stuck; consider %s kill" % sys.argv[0])
282+
fail("Daemon is stuck; consider %s kill" % sys.argv[0])
278283
else:
279284
print("Daemon stopped")
280285

@@ -286,7 +291,7 @@ def do_kill(args: argparse.Namespace) -> None:
286291
try:
287292
kill(pid)
288293
except OSError as err:
289-
sys.exit(str(err))
294+
fail(str(err))
290295
else:
291296
print("Daemon killed")
292297

@@ -332,11 +337,11 @@ def check_output(response: Dict[str, Any], verbose: bool, junit_xml: Optional[st
332337
Call sys.exit() unless the status code is zero.
333338
"""
334339
if 'error' in response:
335-
sys.exit(response['error'])
340+
fail(response['error'])
336341
try:
337342
out, err, status_code = response['out'], response['err'], response['status']
338343
except KeyError:
339-
sys.exit("Response: %s" % str(response))
344+
fail("Response: %s" % str(response))
340345
sys.stdout.write(out)
341346
sys.stderr.write(err)
342347
if verbose:

test-data/unit/daemon.test

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,41 +68,41 @@ def plugin(version): return Dummy
6868
[case testDaemonStatusKillRestartRecheck]
6969
$ dmypy status
7070
No status file found
71-
== Return code: 1
71+
== Return code: 2
7272
$ dmypy stop
7373
No status file found
74-
== Return code: 1
74+
== Return code: 2
7575
$ dmypy kill
7676
No status file found
77-
== Return code: 1
77+
== Return code: 2
7878
$ dmypy recheck
7979
No status file found
80-
== Return code: 1
80+
== Return code: 2
8181
$ dmypy start -- --follow-imports=error
8282
Daemon started
8383
$ dmypy status
8484
Daemon is up and running
8585
$ dmypy start
8686
Daemon is still alive
87-
== Return code: 1
87+
== Return code: 2
8888
$ dmypy restart -- --follow-imports=error
8989
Daemon stopped
9090
Daemon started
9191
$ dmypy stop
9292
Daemon stopped
9393
$ dmypy status
9494
No status file found
95-
== Return code: 1
95+
== Return code: 2
9696
$ dmypy restart -- --follow-imports=error
9797
Daemon started
9898
$ dmypy recheck
9999
Command 'recheck' is only valid after a 'check' command
100-
== Return code: 1
100+
== Return code: 2
101101
$ dmypy kill
102102
Daemon killed
103103
$ dmypy status
104104
Daemon has died
105-
== Return code: 1
105+
== Return code: 2
106106

107107
[case testDaemonRecheck]
108108
$ dmypy start -- --follow-imports=error

0 commit comments

Comments
 (0)