Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Daniel Brötzmann
gajim
Commits
c794ddcf
Commit
c794ddcf
authored
Dec 24, 2021
by
Daniel Brötzmann
Browse files
Exceptions: Rework and basic Sentry integration
parent
c2feb0ef
Pipeline
#9012
passed with stages
in 5 minutes and 46 seconds
Changes
6
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
gajim/common/app.py
View file @
c794ddcf
...
...
@@ -139,6 +139,7 @@ def __init__(self):
'IDLE'
:
False
,
'APPINDICATOR'
:
False
,
'AYATANA_APPINDICATOR'
:
False
,
'SENTRY_SDK'
:
False
,
}
_tasks
:
dict
[
int
,
list
[
Any
]]
=
defaultdict
(
list
)
...
...
@@ -304,6 +305,13 @@ def detect_dependencies() -> None:
except
(
ImportError
,
ValueError
):
pass
# SENTRY SDK
try
:
import
sentry_sdk
# pylint: disable=unused-import
_dependencies
[
'SENTRY_SDK'
]
=
True
except
ImportError
:
pass
# Print results
for
dep
,
val
in
_dependencies
.
items
():
log
(
'gajim'
).
info
(
'%-13s %s'
,
dep
,
val
)
...
...
gajim/common/helpers.py
View file @
c794ddcf
...
...
@@ -78,6 +78,7 @@
from
OpenSSL.crypto
import
FILETYPE_PEM
from
gi.repository
import
Gio
from
gi.repository
import
GLib
from
gi.repository
import
GObject
import
precis_i18n.codec
# pylint: disable=unused-import
from
gajim.common
import
app
...
...
@@ -1426,3 +1427,39 @@ def get_start_of_day(date_time: datetime) -> datetime:
minute
=
0
,
second
=
0
,
microsecond
=
0
)
def
get_os_name
()
->
str
:
if
sys
.
platform
in
(
'win32'
,
'darwin'
):
return
platform
.
system
()
if
os
.
name
==
'posix'
:
try
:
import
distro
return
distro
.
name
(
pretty
=
True
)
except
ImportError
:
return
platform
.
system
()
return
''
def
get_os_version
()
->
str
:
if
sys
.
platform
in
(
'win32'
,
'darwin'
):
return
platform
.
release
()
if
os
.
name
==
'posix'
:
try
:
import
distro
return
distro
.
version
(
pretty
=
True
)
except
ImportError
:
return
platform
.
release
()
return
''
def
get_gobject_version
()
->
str
:
gobject_ver
=
'.'
.
join
(
map
(
str
,
GObject
.
pygobject_version
))
return
gobject_ver
def
get_glib_version
()
->
str
:
glib_ver
=
'.'
.
join
(
map
(
str
,
[
GLib
.
MAJOR_VERSION
,
GLib
.
MINOR_VERSION
,
GLib
.
MICRO_VERSION
]))
return
glib_ver
gajim/common/setting_values.py
View file @
c794ddcf
...
...
@@ -149,6 +149,7 @@ class _ACCOUNT_DEFAULT:
'video_framerate'
,
'video_input_device'
,
'video_size'
,
'sentry_endpoint'
,
]
AllSettings
=
Literal
[
BoolSettings
,
IntSettings
,
StringSettings
]
...
...
@@ -268,6 +269,7 @@ class _ACCOUNT_DEFAULT:
'gc_print_join_left_default'
:
False
,
'check_for_update'
:
True
,
'last_update_check'
:
''
,
'sentry_endpoint'
:
'http://a82a9566841e4844b711d1813680496f@194.59.207.70:9000/3'
,
'always_ask_for_status_message'
:
False
,
'show_send_message_button'
:
False
,
'workspace_order'
:
[],
...
...
gajim/data/gui/exception_dialog.ui
View file @
c794ddcf
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.3
6.0
-->
<!-- Generated with glade 3.3
8.2
-->
<interface>
<requires
lib=
"gtk+"
version=
"3.22"
/>
<object
class=
"GtkApplicationWindow"
id=
"exception_dialog"
>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"window_position"
>
center
</property>
<property
name=
"type_hint"
>
dialog
</property>
<requires
lib=
"gtk+"
version=
"3.24"
/>
<object
class=
"GtkBox"
id=
"exception_box"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can-focus"
>
False
</property>
<property
name=
"orientation"
>
vertical
</property>
<child>
<object
class=
"GtkInfoBar"
id=
"infobar"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can-focus"
>
False
</property>
<property
name=
"revealed"
>
False
</property>
<child
internal-child=
"action_area"
>
<object
class=
"GtkButtonBox"
>
<property
name=
"can-focus"
>
False
</property>
<property
name=
"spacing"
>
6
</property>
<property
name=
"layout-style"
>
end
</property>
<child>
<object
class=
"GtkLabel"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can-focus"
>
False
</property>
<property
name=
"label"
translatable=
"yes"
>
Install
<
tt
>
sentry-sdk
<
/tt
>
to make reporting issues easier.
</property>
<property
name=
"use-markup"
>
True
</property>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
0
</property>
</packing>
</child>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
False
</property>
<property
name=
"position"
>
0
</property>
</packing>
</child>
<child
internal-child=
"content_area"
>
<object
class=
"GtkBox"
>
<property
name=
"can-focus"
>
False
</property>
<property
name=
"spacing"
>
16
</property>
<child>
<object
class=
"GtkImage"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can-focus"
>
False
</property>
<property
name=
"icon-name"
>
dialog-information-symbolic
</property>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
0
</property>
</packing>
</child>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
False
</property>
<property
name=
"position"
>
0
</property>
</packing>
</child>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
0
</property>
</packing>
</child>
<child>
<object
class=
"GtkBox"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can
_
focus"
>
False
</property>
<property
name=
"border
_
width"
>
18
</property>
<property
name=
"can
-
focus"
>
False
</property>
<property
name=
"border
-
width"
>
18
</property>
<property
name=
"orientation"
>
vertical
</property>
<property
name=
"spacing"
>
12
</property>
<child>
<object
class=
"GtkBox"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can
_
focus"
>
False
</property>
<property
name=
"spacing"
>
1
2
</property>
<property
name=
"can
-
focus"
>
False
</property>
<property
name=
"spacing"
>
2
4
</property>
<child>
<object
class=
"GtkImage"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can
_
focus"
>
False
</property>
<property
name=
"valign"
>
center
</property>
<property
name=
"icon
_
name"
>
dialog-error
</property>
<property
name=
"can
-
focus"
>
False
</property>
<property
name=
"valign"
>
start
</property>
<property
name=
"icon
-
name"
>
dialog-error
</property>
<property
name=
"icon_size"
>
6
</property>
</object>
<packing>
...
...
@@ -35,17 +95,17 @@
<child>
<object
class=
"GtkBox"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can
_
focus"
>
False
</property>
<property
name=
"can
-
focus"
>
False
</property>
<property
name=
"orientation"
>
vertical
</property>
<property
name=
"spacing"
>
6
</property>
<child>
<object
class=
"GtkLabel"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can
_
focus"
>
False
</property>
<property
name=
"can
-
focus"
>
False
</property>
<property
name=
"halign"
>
start
</property>
<property
name=
"label"
translatable=
"yes"
>
Sorry, that should not have happened
</property>
<property
name=
"wrap"
>
True
</property>
<property
name=
"max
_
width
_
chars"
>
3
0
</property>
<property
name=
"max
-
width
-
chars"
>
5
0
</property>
<property
name=
"xalign"
>
0
</property>
<style>
<class
name=
"large-header"
/>
...
...
@@ -60,14 +120,17 @@
<child>
<object
class=
"GtkLabel"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can
_
focus"
>
False
</property>
<property
name=
"can
-
focus"
>
False
</property>
<property
name=
"halign"
>
start
</property>
<property
name=
"label"
translatable=
"yes"
>
Gajim encountered an error.
A report is shown below.
By reporting this bug you might help people to fix this
.
</property>
<property
name=
"label"
translatable=
"yes"
>
Gajim encountered an error.
Please help us fixing this issue by sending this report
.
</property>
<property
name=
"wrap"
>
True
</property>
<property
name=
"max
_
width
_
chars"
>
60
</property>
<property
name=
"max
-
width
-
chars"
>
60
</property>
<property
name=
"lines"
>
3
</property>
<property
name=
"xalign"
>
0
</property>
<style>
<class
name=
"dim-label"
/>
</style>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
...
...
@@ -75,9 +138,95 @@ By reporting this bug you might help people to fix this.</property>
<property
name=
"position"
>
1
</property>
</packing>
</child>
<child>
<object
class=
"GtkExpander"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can-focus"
>
True
</property>
<property
name=
"label-fill"
>
True
</property>
<property
name=
"resize-toplevel"
>
True
</property>
<child>
<object
class=
"GtkScrolledWindow"
>
<property
name=
"height-request"
>
200
</property>
<property
name=
"visible"
>
True
</property>
<property
name=
"can-focus"
>
True
</property>
<property
name=
"shadow-type"
>
in
</property>
<child>
<object
class=
"GtkTextView"
id=
"exception_view"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can-focus"
>
True
</property>
<property
name=
"hexpand"
>
True
</property>
<property
name=
"vexpand"
>
True
</property>
<property
name=
"editable"
>
False
</property>
<property
name=
"left-margin"
>
4
</property>
<property
name=
"right-margin"
>
4
</property>
<property
name=
"top-margin"
>
4
</property>
<property
name=
"bottom-margin"
>
4
</property>
<property
name=
"accepts-tab"
>
False
</property>
<property
name=
"monospace"
>
True
</property>
</object>
</child>
</object>
</child>
<child
type=
"label"
>
<object
class=
"GtkLabel"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can-focus"
>
False
</property>
<property
name=
"label"
translatable=
"yes"
>
View Report
</property>
</object>
</child>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
2
</property>
</packing>
</child>
<child>
<object
class=
"GtkBox"
id=
"user_feedback_box"
>
<property
name=
"can-focus"
>
False
</property>
<property
name=
"margin-top"
>
6
</property>
<property
name=
"orientation"
>
vertical
</property>
<property
name=
"spacing"
>
6
</property>
<child>
<object
class=
"GtkLabel"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can-focus"
>
False
</property>
<property
name=
"halign"
>
start
</property>
<property
name=
"label"
translatable=
"yes"
>
Additional Infos:
</property>
<property
name=
"wrap"
>
True
</property>
<property
name=
"xalign"
>
0
</property>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
0
</property>
</packing>
</child>
<child>
<object
class=
"GtkEntry"
id=
"user_feedback_entry"
>
<property
name=
"width-request"
>
400
</property>
<property
name=
"visible"
>
True
</property>
<property
name=
"can-focus"
>
True
</property>
<property
name=
"halign"
>
start
</property>
<property
name=
"activates-default"
>
True
</property>
<property
name=
"placeholder-text"
translatable=
"yes"
>
Add some details…
</property>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
1
</property>
</packing>
</child>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
3
</property>
</packing>
</child>
</object>
<packing>
<property
name=
"expand"
>
Fals
e
</property>
<property
name=
"expand"
>
Tru
e
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
1
</property>
</packing>
...
...
@@ -90,79 +239,72 @@ By reporting this bug you might help people to fix this.</property>
</packing>
</child>
<child>
<object
class=
"GtkB
uttonB
ox"
>
<object
class=
"GtkBox"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
False
</property>
<property
name=
"spacing"
>
6
</property>
<property
name=
"layout_style"
>
end
</property>
<property
name=
"can-focus"
>
False
</property>
<property
name=
"spacing"
>
12
</property>
<child>
<object
class=
"GtkButton"
id=
"close_b
t
n"
>
<property
name=
"label"
>
_Close
</property>
<object
class=
"GtkButton"
id=
"close_b
utto
n"
>
<property
name=
"label"
translatable=
"yes"
>
_Close
</property>
<property
name=
"visible"
>
True
</property>
<property
name=
"can
_
focus"
>
True
</property>
<property
name=
"receives
_
default"
>
Tru
e
</property>
<property
name=
"use
_
underline"
>
True
</property>
<signal
name=
"clicked"
handler=
"on_close_clicked"
swapped=
"no"
/>
<property
name=
"can
-
focus"
>
True
</property>
<property
name=
"receives
-
default"
>
Fals
e
</property>
<property
name=
"use
-
underline"
>
True
</property>
<signal
name=
"clicked"
handler=
"
_
on_close_clicked"
swapped=
"no"
/>
</object>
<packing>
<property
name=
"expand"
>
Tru
e
</property>
<property
name=
"expand"
>
Fals
e
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"pack-type"
>
end
</property>
<property
name=
"position"
>
0
</property>
</packing>
</child>
<child>
<object
class=
"GtkButton"
id=
"report_b
t
n"
>
<property
name=
"label"
translatable=
"yes"
>
_Report
Bug
</property>
<object
class=
"GtkButton"
id=
"report_b
utto
n"
>
<property
name=
"label"
translatable=
"yes"
>
Send
_Report
</property>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
True
</property>
<property
name=
"receives_default"
>
True
</property>
<property
name=
"use_underline"
>
True
</property>
<signal
name=
"clicked"
handler=
"on_report_clicked"
swapped=
"no"
/>
<property
name=
"can-focus"
>
True
</property>
<property
name=
"can-default"
>
True
</property>
<property
name=
"receives-default"
>
True
</property>
<property
name=
"use-underline"
>
True
</property>
<signal
name=
"clicked"
handler=
"_on_report_clicked"
swapped=
"no"
/>
<style>
<class
name=
"suggested-action"
/>
</style>
</object>
<packing>
<property
name=
"expand"
>
Tru
e
</property>
<property
name=
"expand"
>
Fals
e
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
1
</property>
<property
name=
"pack-type"
>
end
</property>
<property
name=
"position"
>
0
</property>
</packing>
</child>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"pack_type"
>
end
</property>
<property
name=
"position"
>
1
</property>
</packing>
</child>
<child>
<object
class=
"GtkScrolledWindow"
>
<property
name=
"height_request"
>
200
</property>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
True
</property>
<property
name=
"vexpand"
>
True
</property>
<property
name=
"shadow_type"
>
in
</property>
<child>
<object
class=
"Gtk
TextView"
id=
"exception_view
"
>
<object
class=
"Gtk
Spinner"
id=
"report_spinner
"
>
<property
name=
"visible"
>
True
</property>
<property
name=
"can_focus"
>
True
</property>
<property
name=
"hexpand"
>
True
</property>
<property
name=
"vexpand"
>
True
</property>
<property
name=
"editable"
>
False
</property>
<property
name=
"left_margin"
>
4
</property>
<property
name=
"right_margin"
>
4
</property>
<property
name=
"accepts_tab"
>
False
</property>
<property
name=
"can-focus"
>
False
</property>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"pack-type"
>
end
</property>
<property
name=
"position"
>
2
</property>
</packing>
</child>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
2
</property>
<property
name=
"pack-type"
>
end
</property>
<property
name=
"position"
>
4
</property>
</packing>
</child>
</object>
<packing>
<property
name=
"expand"
>
False
</property>
<property
name=
"fill"
>
True
</property>
<property
name=
"position"
>
1
</property>
</packing>
</child>
</object>
</interface>
gajim/gtk/exception.py
View file @
c794ddcf
...
...
@@ -17,29 +17,46 @@
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
from
typing
import
Type
from
types
import
TracebackType
import
sys
import
os
import
json
from
json.decoder
import
JSONDecodeError
import
traceback
import
threading
import
webbrowser
import
platform
from
io
import
StringIO
from
urllib.parse
import
urlencode
from
gi.repository
import
Gdk
from
gi.repository
import
Gtk
from
gi.repository
import
GObject
from
gi.repository
import
GLib
from
gi.repository
import
Soup
import
nbxmpp
import
gajim
from
gajim.common
import
app
from
gajim.common
import
configpaths
from
gajim.common.helpers
import
get_glib_version
from
gajim.common.helpers
import
get_gobject_version
from
gajim.common.helpers
import
get_os_name
from
gajim.common.helpers
import
get_os_version
from
gajim.common.i18n
import
_
from
.builder
import
get_builder
from
.util
import
get_gtk_version
try
:
import
sentry_sdk
except
ImportError
:
pass
_exception_in_progress
=
threading
.
Lock
()
ISSUE_TEXT
=
'''## Versions
ISSUE_URL
=
'https://dev.gajim.org/gajim/gajim/issues/new'
ISSUE_TEXT
=
'''## Versions:
- OS: {}
- GTK Version: {}
- PyGObject Version: {}
...
...
@@ -55,7 +72,10 @@
...'''
def
_hook
(
type_
,
value
,
tb
):
def
_hook
(
type_
:
Type
[
BaseException
],
value
:
BaseException
,
tb
:
TracebackType
)
->
None
:
if
not
_exception_in_progress
.
acquire
(
False
):
# Exceptions have piled up, so we use the default exception
# handler for such exceptions
...
...
@@ -66,65 +86,135 @@ def _hook(type_, value, tb):
_exception_in_progress
.
release
()
class
ExceptionDialog
():
def
__init__
(
self
,
type_
,
value
,
tb
):
class
ExceptionDialog
(
Gtk
.
ApplicationWindow
):
def
__init__
(
self
,
type_
:
Type
[
BaseException
],
value
:
BaseException
,
tb
:
TracebackType
)
->
None
:
Gtk
.
ApplicationWindow
.
__init__
(
self
)
self
.
set_application
(
app
.
app
)
self
.
set_type_hint
(
Gdk
.
WindowTypeHint
.
DIALOG
)
self
.
set_position
(
Gtk
.
WindowPosition
.
CENTER
)
self
.
set_show_menubar
(
False
)
self
.
set_resizable
(
True
)
self
.
set_default_size
(
700
,
-
1
)
self
.
set_title
(
_
(
'Gajim - Error'
))
self
.
_traceback_data
=
(
type_
,
value
,
tb
)
self
.
_sentry_available
=
app
.
is_installed
(
'SENTRY_SDK'
)
self
.
_sentry_endpoint
=
app
.
settings
.
get
(
'sentry_endpoint'
)
path
=
configpaths
.
get
(
'GUI'
)
/
'exception_dialog.ui'
self
.
_ui
=
get_builder
(
path
.
resolve
())
self
.
_ui
.
connect_signals
(
self
)
self
.
add
(
self
.
_ui
.
exception_box
)
self
.
_ui
.
report_btn
.
grab_focus
()
if
not
self
.
_sentry_available
:
self
.
_ui
.
user_feedback_box
.
set_no_show_all
(
True
)
self
.
_ui
.
infobar
.
set_revealed
(
True
)
self
.
_ui
.
report_button
.
grab_focus
()
self
.
_ui
.
report_button
.
grab_default
()
buffer_
=
self
.
_ui
.
exception_view
.
get_buffer
()
trace
=
StringIO
()
traceback
.
print_exception
(
type_
,
value
,
tb
,
None
,
trace
)
self
.
text
=
self
.
get_issue_text
(
trace
.
getvalue
())
buffer_
.
set_text
(
self
.
text
)
print
(
self
.
text
,
file
=
sys
.
stderr
)
self
.
_ui
.
exception_view
.
set_editable
(
False
)
self
.
_ui
.
exception_dialog
.
show
()
self
.
_issue_text
=
self
.
_get_issue_text
(
trace
.
getvalue
())
buffer_
=
self
.
_ui
.
exception_view
.
get_buffer
()
buffer_
.
set_text
(
self
.
_issue_text
)
self
.
_ui
.
connect_signals
(
self
)
self
.
show_all
()
if
self
.
_sentry_available
:
self
.
_ui
.
user_feedback_entry
.
grab_focus
()
def
on_report_clicked
(
self
,
*
args
):
issue_url
=
'https://dev.gajim.org/gajim/gajim/issues/new'
params
=
{
'issue[description]'
:
self
.
text
}
url
=
'{}?{}'
.
format
(
issue_url
,
urlencode
(
params
))
def
_on_report_clicked
(
self
,
_button
:
Gtk
.
Button
)
->
None
:
if
self
.
_sentry_available
:
self
.
_report_via_sentry
()
return
params
=
{
'issue[description]'
:
self
.
_issue_text
}
url
=
f
'
{
ISSUE_URL
}
?
{
urlencode
(
params
)
}
'
webbrowser
.
open
(
url
,
new
=
2
)
self
.
destroy
()
def
on_close_clicked
(
self
,
*
args
)
:
self
.
_ui
.
exception_dialog
.
destroy
()
def
_
on_close_clicked
(
self
,
_button
:
Gtk
.
Button
)
->
None
:
self
.
destroy
()
@
staticmethod
def
get_issue_text
(
traceback_text
):
gtk_ver
=
'%i.%i.%i'
%
(
Gtk
.
get_major_version
(),
Gtk
.
get_minor_version
(),
Gtk
.
get_micro_version
())
gobject_ver
=
'.'
.
join
(
map
(
str
,
GObject
.
pygobject_version
))
glib_ver
=
'.'
.
join
(
map
(
str
,
[
GLib
.
MAJOR_VERSION
,
GLib
.
MINOR_VERSION
,
GLib
.
MICRO_VERSION
]))
return
ISSUE_TEXT
.
format
(
get_os_info
(),
gtk_ver
,
gobject_ver
,
glib_ver
,
nbxmpp
.
__version__
,
gajim
.
__version__
,
traceback_text
)
def
init
():
if
os
.
name
==
'nt'
or
not
sys
.
stderr
.
isatty
():
def
_get_issue_text
(
traceback_text
:
str
)
->
str
:
return
ISSUE_TEXT
.
format
(
f
'
{
get_os_name
()
}
{
get_os_version
()
}
'
,
get_gtk_version
(),
get_gobject_version
(),