logxpy 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- logxpy/__init__.py +126 -0
- logxpy/_action.py +958 -0
- logxpy/_async.py +186 -0
- logxpy/_base.py +80 -0
- logxpy/_compat.py +71 -0
- logxpy/_config.py +45 -0
- logxpy/_dest.py +88 -0
- logxpy/_errors.py +58 -0
- logxpy/_fmt.py +68 -0
- logxpy/_generators.py +136 -0
- logxpy/_mask.py +23 -0
- logxpy/_message.py +195 -0
- logxpy/_output.py +517 -0
- logxpy/_pool.py +93 -0
- logxpy/_traceback.py +126 -0
- logxpy/_types.py +71 -0
- logxpy/_util.py +56 -0
- logxpy/_validation.py +486 -0
- logxpy/_version.py +21 -0
- logxpy/cli.py +61 -0
- logxpy/dask.py +172 -0
- logxpy/decorators.py +268 -0
- logxpy/filter.py +124 -0
- logxpy/journald.py +88 -0
- logxpy/json.py +149 -0
- logxpy/loggerx.py +253 -0
- logxpy/logwriter.py +84 -0
- logxpy/parse.py +191 -0
- logxpy/prettyprint.py +173 -0
- logxpy/serializers.py +36 -0
- logxpy/stdlib.py +23 -0
- logxpy/tai64n.py +45 -0
- logxpy/testing.py +472 -0
- logxpy/tests/__init__.py +9 -0
- logxpy/tests/common.py +36 -0
- logxpy/tests/strategies.py +231 -0
- logxpy/tests/test_action.py +1751 -0
- logxpy/tests/test_api.py +86 -0
- logxpy/tests/test_async.py +67 -0
- logxpy/tests/test_compat.py +13 -0
- logxpy/tests/test_config.py +21 -0
- logxpy/tests/test_coroutines.py +105 -0
- logxpy/tests/test_dask.py +211 -0
- logxpy/tests/test_decorators.py +54 -0
- logxpy/tests/test_filter.py +122 -0
- logxpy/tests/test_fmt.py +42 -0
- logxpy/tests/test_generators.py +292 -0
- logxpy/tests/test_journald.py +246 -0
- logxpy/tests/test_json.py +208 -0
- logxpy/tests/test_loggerx.py +44 -0
- logxpy/tests/test_logwriter.py +262 -0
- logxpy/tests/test_message.py +334 -0
- logxpy/tests/test_output.py +921 -0
- logxpy/tests/test_parse.py +309 -0
- logxpy/tests/test_pool.py +55 -0
- logxpy/tests/test_prettyprint.py +303 -0
- logxpy/tests/test_pyinstaller.py +35 -0
- logxpy/tests/test_serializers.py +36 -0
- logxpy/tests/test_stdlib.py +73 -0
- logxpy/tests/test_tai64n.py +66 -0
- logxpy/tests/test_testing.py +1051 -0
- logxpy/tests/test_traceback.py +251 -0
- logxpy/tests/test_twisted.py +814 -0
- logxpy/tests/test_util.py +45 -0
- logxpy/tests/test_validation.py +989 -0
- logxpy/twisted.py +265 -0
- logxpy-0.1.0.dist-info/METADATA +100 -0
- logxpy-0.1.0.dist-info/RECORD +72 -0
- logxpy-0.1.0.dist-info/WHEEL +5 -0
- logxpy-0.1.0.dist-info/entry_points.txt +2 -0
- logxpy-0.1.0.dist-info/licenses/LICENSE +201 -0
- logxpy-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for L{eliot._traceback}.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from unittest import TestCase, SkipTest
|
|
6
|
+
import traceback
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from twisted.python.failure import Failure
|
|
11
|
+
except ImportError:
|
|
12
|
+
Failure = None
|
|
13
|
+
|
|
14
|
+
from .._traceback import write_traceback, writeFailure, _writeTracebackMessage
|
|
15
|
+
from ..testing import (
|
|
16
|
+
assertContainsFields,
|
|
17
|
+
validateLogging,
|
|
18
|
+
capture_logging,
|
|
19
|
+
MemoryLogger,
|
|
20
|
+
)
|
|
21
|
+
from .._errors import register_exception_extractor
|
|
22
|
+
from .test_action import make_error_extraction_tests
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def assert_expected_traceback(test, logger, message, exception, expected_traceback):
|
|
26
|
+
"""Assert we logged the given exception and the expected traceback."""
|
|
27
|
+
lines = expected_traceback.split("\n")
|
|
28
|
+
# Remove source code lines:
|
|
29
|
+
expected_traceback = "\n".join([l for l in lines if not l.startswith(" ")])
|
|
30
|
+
assertContainsFields(
|
|
31
|
+
test,
|
|
32
|
+
message,
|
|
33
|
+
{
|
|
34
|
+
"message_type": "eliot:traceback",
|
|
35
|
+
"exception": RuntimeError,
|
|
36
|
+
"reason": exception,
|
|
37
|
+
"traceback": expected_traceback,
|
|
38
|
+
},
|
|
39
|
+
)
|
|
40
|
+
logger.flushTracebacks(RuntimeError)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class TracebackLoggingTests(TestCase):
|
|
44
|
+
"""
|
|
45
|
+
Tests for L{write_traceback} and L{writeFailure}.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
@validateLogging(None)
|
|
49
|
+
def test_write_traceback_implicit(self, logger):
|
|
50
|
+
"""
|
|
51
|
+
L{write_traceback} with no arguments writes the current traceback to
|
|
52
|
+
the log.
|
|
53
|
+
"""
|
|
54
|
+
e = None
|
|
55
|
+
|
|
56
|
+
def raiser():
|
|
57
|
+
raise RuntimeError("because")
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
raiser()
|
|
61
|
+
except Exception as exception:
|
|
62
|
+
expected_traceback = traceback.format_exc()
|
|
63
|
+
write_traceback(logger)
|
|
64
|
+
e = exception
|
|
65
|
+
assert_expected_traceback(
|
|
66
|
+
self, logger, logger.messages[0], e, expected_traceback
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
@validateLogging(None)
|
|
70
|
+
def test_write_traceback_explicit(self, logger):
|
|
71
|
+
"""
|
|
72
|
+
L{write_traceback} with explicit arguments writes the given traceback
|
|
73
|
+
to the log.
|
|
74
|
+
"""
|
|
75
|
+
e = None
|
|
76
|
+
|
|
77
|
+
def raiser():
|
|
78
|
+
raise RuntimeError("because")
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
raiser()
|
|
82
|
+
except Exception as exception:
|
|
83
|
+
expected_traceback = traceback.format_exc()
|
|
84
|
+
write_traceback(logger, exc_info=sys.exc_info())
|
|
85
|
+
e = exception
|
|
86
|
+
assert_expected_traceback(
|
|
87
|
+
self, logger, logger.messages[0], e, expected_traceback
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
@capture_logging(None)
|
|
91
|
+
def test_writeTracebackDefaultLogger(self, logger):
|
|
92
|
+
"""
|
|
93
|
+
L{write_traceback} writes to the default log, if none is
|
|
94
|
+
specified.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
def raiser():
|
|
98
|
+
raise RuntimeError("because")
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
raiser()
|
|
102
|
+
except Exception:
|
|
103
|
+
write_traceback()
|
|
104
|
+
|
|
105
|
+
message = logger.messages[0]
|
|
106
|
+
assertContainsFields(self, message, {"message_type": "eliot:traceback"})
|
|
107
|
+
logger.flushTracebacks(RuntimeError)
|
|
108
|
+
|
|
109
|
+
@validateLogging(None)
|
|
110
|
+
def test_writeFailure(self, logger):
|
|
111
|
+
"""
|
|
112
|
+
L{writeFailure} writes a L{Failure} to the log.
|
|
113
|
+
"""
|
|
114
|
+
if Failure is None:
|
|
115
|
+
raise SkipTest("Twisted unavailable")
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
raise RuntimeError("because")
|
|
119
|
+
except:
|
|
120
|
+
failure = Failure()
|
|
121
|
+
expectedTraceback = failure.getBriefTraceback()
|
|
122
|
+
writeFailure(failure, logger)
|
|
123
|
+
message = logger.messages[0]
|
|
124
|
+
assertContainsFields(
|
|
125
|
+
self,
|
|
126
|
+
message,
|
|
127
|
+
{
|
|
128
|
+
"message_type": "eliot:traceback",
|
|
129
|
+
"exception": RuntimeError,
|
|
130
|
+
"reason": failure.value,
|
|
131
|
+
"traceback": expectedTraceback,
|
|
132
|
+
},
|
|
133
|
+
)
|
|
134
|
+
logger.flushTracebacks(RuntimeError)
|
|
135
|
+
|
|
136
|
+
@capture_logging(None)
|
|
137
|
+
def test_writeFailureDefaultLogger(self, logger):
|
|
138
|
+
"""
|
|
139
|
+
L{writeFailure} writes to the default log, if none is
|
|
140
|
+
specified.
|
|
141
|
+
"""
|
|
142
|
+
if Failure is None:
|
|
143
|
+
raise SkipTest("Twisted unavailable")
|
|
144
|
+
|
|
145
|
+
try:
|
|
146
|
+
raise RuntimeError("because")
|
|
147
|
+
except:
|
|
148
|
+
failure = Failure()
|
|
149
|
+
writeFailure(failure)
|
|
150
|
+
message = logger.messages[0]
|
|
151
|
+
assertContainsFields(self, message, {"message_type": "eliot:traceback"})
|
|
152
|
+
logger.flushTracebacks(RuntimeError)
|
|
153
|
+
|
|
154
|
+
@validateLogging(None)
|
|
155
|
+
def test_writeFailureResult(self, logger):
|
|
156
|
+
"""
|
|
157
|
+
L{writeFailure} returns C{None}.
|
|
158
|
+
"""
|
|
159
|
+
if Failure is None:
|
|
160
|
+
raise SkipTest("Twisted unavailable")
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
raise RuntimeError("because")
|
|
164
|
+
except:
|
|
165
|
+
result = writeFailure(Failure(), logger)
|
|
166
|
+
self.assertIs(result, None)
|
|
167
|
+
logger.flushTracebacks(RuntimeError)
|
|
168
|
+
|
|
169
|
+
@validateLogging(None)
|
|
170
|
+
def test_serialization(self, logger):
|
|
171
|
+
"""
|
|
172
|
+
L{_writeTracebackMessage} serializes exceptions to string values and
|
|
173
|
+
types to FQPN.
|
|
174
|
+
"""
|
|
175
|
+
try:
|
|
176
|
+
raise KeyError(123)
|
|
177
|
+
except:
|
|
178
|
+
exc_info = sys.exc_info()
|
|
179
|
+
_writeTracebackMessage(logger, *exc_info)
|
|
180
|
+
serialized = logger.serialize()[0]
|
|
181
|
+
assertContainsFields(
|
|
182
|
+
self,
|
|
183
|
+
serialized,
|
|
184
|
+
{"exception": "%s.KeyError" % (KeyError.__module__,), "reason": "123"},
|
|
185
|
+
)
|
|
186
|
+
logger.flushTracebacks(KeyError)
|
|
187
|
+
|
|
188
|
+
@validateLogging(None)
|
|
189
|
+
def test_badException(self, logger):
|
|
190
|
+
"""
|
|
191
|
+
L{_writeTracebackMessage} logs a message even if given a bad exception.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
class BadException(Exception):
|
|
195
|
+
def __str__(self):
|
|
196
|
+
raise TypeError()
|
|
197
|
+
|
|
198
|
+
try:
|
|
199
|
+
raise BadException()
|
|
200
|
+
except BadException:
|
|
201
|
+
exc_info = sys.exc_info()
|
|
202
|
+
_writeTracebackMessage(logger, *exc_info)
|
|
203
|
+
self.assertEqual(
|
|
204
|
+
logger.serialize()[0]["reason"],
|
|
205
|
+
"eliot: unknown, str() raised exception",
|
|
206
|
+
)
|
|
207
|
+
logger.flushTracebacks(BadException)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def get_traceback_messages(exception):
|
|
211
|
+
"""
|
|
212
|
+
Given an exception instance generate a traceback Eliot message.
|
|
213
|
+
"""
|
|
214
|
+
logger = MemoryLogger()
|
|
215
|
+
try:
|
|
216
|
+
raise exception
|
|
217
|
+
except exception.__class__:
|
|
218
|
+
write_traceback(logger)
|
|
219
|
+
# MemoryLogger.validate() mutates messages:
|
|
220
|
+
# https://github.com/itamarst/eliot/issues/243
|
|
221
|
+
messages = [message.copy() for message in logger.messages]
|
|
222
|
+
logger.validate()
|
|
223
|
+
return messages
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class TracebackExtractionTests(make_error_extraction_tests(get_traceback_messages)):
|
|
227
|
+
"""
|
|
228
|
+
Error extraction tests for tracebacks.
|
|
229
|
+
"""
|
|
230
|
+
|
|
231
|
+
def test_regular_fields(self):
|
|
232
|
+
"""
|
|
233
|
+
The normal traceback fields are still present when error
|
|
234
|
+
extraction is used.
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
class MyException(Exception):
|
|
238
|
+
pass
|
|
239
|
+
|
|
240
|
+
register_exception_extractor(MyException, lambda e: {"key": e.args[0]})
|
|
241
|
+
exception = MyException("because")
|
|
242
|
+
messages = get_traceback_messages(exception)
|
|
243
|
+
assertContainsFields(
|
|
244
|
+
self,
|
|
245
|
+
messages[0],
|
|
246
|
+
{
|
|
247
|
+
"message_type": "eliot:traceback",
|
|
248
|
+
"reason": exception,
|
|
249
|
+
"exception": MyException,
|
|
250
|
+
},
|
|
251
|
+
)
|