1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
import contextlib
import unittest
import inspect
import warnings
import functools
import sys
from collections import namedtuple
from io import StringIO
import gi
from gi import PyGIDeprecationWarning
from gi.repository import GLib
ExceptionInfo = namedtuple("ExceptionInfo", ["type", "value", "traceback"])
"""The type used for storing exceptions used by capture_exceptions()"""
@contextlib.contextmanager
def capture_exceptions():
"""Installs a temporary sys.excepthook which records all exceptions
instead of printing them.
"""
exceptions = []
def custom_excepthook(*args):
exceptions.append(ExceptionInfo(*args))
old_hook = sys.excepthook
sys.excepthook = custom_excepthook
try:
yield exceptions
finally:
sys.excepthook = old_hook
def ignore_gi_deprecation_warnings(func_or_class):
"""A unittest class and function decorator which makes them ignore
PyGIDeprecationWarning.
"""
if inspect.isclass(func_or_class):
assert issubclass(func_or_class, unittest.TestCase)
cls = func_or_class
for name, value in cls.__dict__.items():
if callable(value) and name.startswith("test_"):
new_value = ignore_gi_deprecation_warnings(value)
setattr(cls, name, new_value)
return cls
else:
func = func_or_class
@functools.wraps(func)
def wrapper(*args, **kwargs):
with capture_gi_deprecation_warnings():
return func(*args, **kwargs)
return wrapper
@contextlib.contextmanager
def capture_gi_deprecation_warnings():
"""Temporarily suppress PyGIDeprecationWarning output and record them"""
with warnings.catch_warnings(record=True) as warn:
warnings.simplefilter('always', category=PyGIDeprecationWarning)
yield warn
@contextlib.contextmanager
def capture_glib_warnings(allow_warnings=False, allow_criticals=False):
"""Temporarily suppress glib warning output and record them.
The test suite is run with G_DEBUG="fatal-warnings fatal-criticals"
by default. Setting allow_warnings and allow_criticals will temporarily
allow warnings or criticals without terminating the test run.
"""
old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags(0))
new_mask = old_mask
if allow_warnings:
new_mask &= ~GLib.LogLevelFlags.LEVEL_WARNING
if allow_criticals:
new_mask &= ~GLib.LogLevelFlags.LEVEL_CRITICAL
GLib.log_set_always_fatal(GLib.LogLevelFlags(new_mask))
GLibWarning = gi._gi.Warning
try:
with warnings.catch_warnings(record=True) as warn:
warnings.filterwarnings('always', category=GLibWarning)
yield warn
finally:
GLib.log_set_always_fatal(old_mask)
@contextlib.contextmanager
def capture_glib_deprecation_warnings():
"""Temporarily suppress glib deprecation warning output and record them"""
GLibWarning = gi._gi.Warning
with warnings.catch_warnings(record=True) as warn:
warnings.filterwarnings(
'always', category=GLibWarning,
message=".+ is deprecated and shouldn't be used anymore\\. "
"It will be removed in a future version\\.")
yield warn
@contextlib.contextmanager
def capture_output():
"""
with capture_output() as (stdout, stderr):
some_action()
print(stdout.getvalue(), stderr.getvalue())
"""
err = StringIO()
out = StringIO()
old_err = sys.stderr
old_out = sys.stdout
sys.stderr = err
sys.stdout = out
try:
yield (out, err)
finally:
sys.stderr = old_err
sys.stdout = old_out
|