Skip to content

Commit c960089

Browse files
committed
PICARD-1718: Moved crash handler code into central function
Avoid code duplication, by still having a rather minimal dependency of internal code.
1 parent 0c5d908 commit c960089

File tree

3 files changed

+51
-72
lines changed

3 files changed

+51
-72
lines changed

picard/__init__.py

+45
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,48 @@ def version_from_string(version_str):
8787
]
8888

8989
api_versions_tuple = [Version.from_string(v) for v in api_versions]
90+
91+
92+
def crash_handler():
93+
"""Implements minimal handling of an exception crashing the application.
94+
This function tries to log the exception to a log file and display
95+
a minimal crash dialog to the user.
96+
This function is supposed to be called from inside an except blog.
97+
"""
98+
# First try to get traceback information and write it to a log file
99+
# with minimum chance to fail.
100+
import sys
101+
from tempfile import NamedTemporaryFile
102+
import traceback
103+
trace = traceback.format_exc()
104+
logfile = None
105+
try:
106+
with NamedTemporaryFile(suffix='.log', prefix='picard-crash-', delete=False) as f:
107+
f.write(trace.encode(errors="replace"))
108+
logfile = f.name
109+
except: # noqa: E722,F722 # pylint: disable=bare-except
110+
print("Failed writing log file {0}".format(logfile), file=sys.stderr)
111+
logfile = None
112+
113+
# Display the crash information to the user as a dialog. This requires
114+
# importing Qt5 and has some potential to fail if things are broken.
115+
from PyQt5.QtCore import Qt, QUrl
116+
from PyQt5.QtWidgets import QApplication, QMessageBox
117+
# assigning QApplication to a variable is required to keep the object alive
118+
_unused = QApplication(sys.argv) # noqa: F841
119+
msgbox = QMessageBox()
120+
msgbox.setIcon(QMessageBox.Critical)
121+
msgbox.setWindowTitle("Picard terminated unexpectedly")
122+
msgbox.setTextFormat(Qt.RichText)
123+
msgbox.setText(
124+
'An unexpected error has caused Picard to crash. '
125+
'Please report this issue on the <a href="https://tickets.metabrainz.org/projects/PICARD">MusicBrainz bug tracker</a>.')
126+
if logfile:
127+
logfile_url = QUrl.fromLocalFile(logfile)
128+
msgbox.setInformativeText(
129+
'A logfile has been written to <a href="{0}">{1}</a>.'
130+
.format(logfile_url.url(), logfile))
131+
msgbox.setDetailedText(trace)
132+
msgbox.setStandardButtons(QMessageBox.Close)
133+
msgbox.setDefaultButton(QMessageBox.Close)
134+
msgbox.exec_()

scripts/picard.in

+3-37
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,7 @@ try:
55
main('%(localedir)s', %(autoupdate)s)
66
except SystemExit:
77
raise # Just continue with a normal application exit
8-
except: # noqa: F722
9-
# First try to get traceback information and write it to a log file
10-
# with minimum chance to fail.
11-
import os
12-
import sys
13-
from tempfile import NamedTemporaryFile
14-
import traceback
15-
trace = traceback.format_exc()
16-
try:
17-
with NamedTemporaryFile(suffix='.log', prefix='picard-crash-', delete=False) as f:
18-
f.write(trace.encode(errors="replace"))
19-
logfile = f.name
20-
except: # noqa: F722
21-
print("Failed writing log file {0}".format(logfile), file=sys.stderr)
22-
logfile = None
23-
24-
# Display the crash information to the user as a dialog. This requires
25-
# importing Qt5 and has some potential to fail if things are broken.
26-
from PyQt5.QtCore import Qt, QUrl
27-
from PyQt5.QtWidgets import QApplication, QMessageBox
28-
_unused = QApplication(sys.argv)
29-
msgbox = QMessageBox()
30-
msgbox.setIcon(QMessageBox.Critical)
31-
msgbox.setWindowTitle("Picard terminated unexpectedly")
32-
msgbox.setTextFormat(Qt.RichText)
33-
msgbox.setText(
34-
'An unexpected error has caused Picard to crash. '
35-
'Please report this issue on the <a href="https://tickets.metabrainz.org/projects/PICARD">MusicBrainz bug tracker</a>.')
36-
if logfile:
37-
logfile_url = QUrl.fromLocalFile(logfile)
38-
msgbox.setInformativeText(
39-
'A logfile has been written to <a href="{0}">{1}</a>.'
40-
.format(logfile_url.url(), logfile))
41-
msgbox.setDetailedText(trace)
42-
msgbox.setStandardButtons(QMessageBox.Close)
43-
msgbox.setDefaultButton(QMessageBox.Close)
44-
msgbox.exec_()
8+
except: # noqa: E722,F722 # pylint: disable=bare-except
9+
from picard import crash_handler
10+
crash_handler()
4511
raise

tagger.py.in

+3-35
Original file line numberDiff line numberDiff line change
@@ -20,39 +20,7 @@ try:
2020
main(os.path.join(basedir, 'locale'), %(autoupdate)s)
2121
except SystemExit:
2222
raise # Just continue with a normal application exit
23-
except: # noqa: F722
24-
# First try to get traceback information and write it to a log file
25-
# with minimum chance to fail.
26-
from tempfile import NamedTemporaryFile
27-
import traceback
28-
trace = traceback.format_exc()
29-
try:
30-
with NamedTemporaryFile(suffix='.log', prefix='picard-crash-', delete=False) as f:
31-
f.write(trace.encode(errors="replace"))
32-
logfile = f.name
33-
except: # noqa: F722
34-
print("Failed writing log file {0}".format(logfile), file=sys.stderr)
35-
logfile = None
36-
37-
# Display the crash information to the user as a dialog. This requires#
38-
# importing Qt5 and has some potential to fail if things are broken.
39-
from PyQt5.QtCore import Qt, QUrl
40-
from PyQt5.QtWidgets import QApplication, QMessageBox
41-
_unused = QApplication(sys.argv)
42-
msgbox = QMessageBox()
43-
msgbox.setIcon(QMessageBox.Critical)
44-
msgbox.setWindowTitle("Picard terminated unexpectedly")
45-
msgbox.setTextFormat(Qt.RichText)
46-
msgbox.setText(
47-
'An unexpected error has caused Picard to crash. '
48-
'Please report this issue on the <a href="https://tickets.metabrainz.org/projects/PICARD">MusicBrainz bug tracker</a>.')
49-
if logfile:
50-
logfile_url = QUrl.fromLocalFile(logfile)
51-
msgbox.setInformativeText(
52-
'A logfile has been written to <a href="{0}">{1}</a>.'
53-
.format(logfile_url.url(), logfile))
54-
msgbox.setDetailedText(trace)
55-
msgbox.setStandardButtons(QMessageBox.Close)
56-
msgbox.setDefaultButton(QMessageBox.Close)
57-
msgbox.exec_()
23+
except: # noqa: E722,F722 # pylint: disable=bare-except
24+
from picard import crash_handler
25+
crash_handler()
5826
raise

0 commit comments

Comments
 (0)