Coverage for torxtools/ctxtools.py: 78%
27 statements
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-18 01:02 +0000
« prev ^ index » next coverage.py v7.5.1, created at 2024-05-18 01:02 +0000
1"""
2Utilities for with-statement contexts
3"""
4# pylint: disable=invalid-name
5import contextlib
6import sys
9class suppress_traceback(contextlib.AbstractContextManager):
10 """
11 Context handler to suppress tracebacks and pretty print an error.
13 In case exception is KeyboardInterrupt, then the error is suppressed.
14 No assumption, error or normal exit, is made for why Ctrl-C was used.
16 Example
17 -------
19 .. code-block::
21 if __name__ == "__main__":
22 with suppress_traceback():
23 main()
24 """
26 def __init__(self, keyboard_exitcode=1, system_exitcode=1, error_exitcode=1):
27 self.keyboard_exitcode = keyboard_exitcode
28 self.system_exitcode = system_exitcode
29 self.error_exitcode = error_exitcode
31 def __exit__(self, exctype, excinst, _exctb):
32 if exctype is None:
33 return True
35 if issubclass(exctype, KeyboardInterrupt):
36 # exit code could be success or error, it all depends on if it's the
37 # normal way of quitting the app, so eat the exception by default.
38 sys.exit(self.keyboard_exitcode)
40 if issubclass(exctype, SystemExit):
41 # sys.exit was called with an exit-code, then re-raise with value
42 with contextlib.suppress(ValueError, TypeError):
43 code = int(excinst.code)
44 sys.exit(code)
46 # sys.exit was called with an message, print and re-reaise with error
47 print(excinst, file=sys.stderr)
48 sys.exit(self.system_exitcode)
50 print(f"error: {excinst}", file=sys.stderr)
51 sys.exit(self.error_exitcode)
54class suppress(contextlib.suppress, contextlib.ContextDecorator):
55 """
56 A version of contextlib.suppress with decorator support.
58 Example
59 -------
61 .. code-block::
63 @contextlib.suppress(ValueError)
64 def foobar():
65 ...
66 """
69class reraise_from_none(contextlib.suppress, contextlib.ContextDecorator):
70 """
71 Similar to contextlib.suppress, but with decorator support, and that
72 re-raises exception from None instead of hiding it.
74 Example
75 -------
77 .. code-block::
79 @contextlib.reraise_from_none(ValueError)
80 def foobar():
81 ...
82 """
84 def __exit__(self, exctype, excinst, _exctb):
85 if exctype is None:
86 return
87 if issubclass(exctype, self._exceptions):
88 raise excinst from None