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