docs for muutils v0.9.1
View Source on GitHub

muutils.logger.exception_context


 1from __future__ import annotations
 2
 3import json
 4from types import TracebackType
 5from typing import Protocol
 6
 7from muutils.json_serialize import json_serialize
 8
 9
10class WritableStream(Protocol):
11    """Protocol for objects that support write operations."""
12
13    def write(self, __s: str) -> int: ...
14
15
16class ExceptionContext:
17    """context manager which catches all exceptions happening while the context is open, `.write()` the exception trace to the given stream, and then raises the exception
18
19
20    for example:
21
22    ```python
23    errorfile = open('error.log', 'w')
24
25    with ExceptionContext(errorfile):
26            # do something that might throw an exception
27            # if it does, the exception trace will be written to errorfile
28            # and then the exception will be raised
29    ```
30
31    """
32
33    def __init__(self, stream: WritableStream) -> None:
34        self.stream: WritableStream = stream
35
36    def __enter__(self) -> ExceptionContext:
37        return self
38
39    def __exit__(
40        self,
41        exc_type: type[BaseException] | None,
42        exc_value: BaseException | None,
43        exc_traceback: TracebackType | None,
44    ) -> bool:
45        if exc_type is not None:
46            self.stream.write(
47                json.dumps(
48                    json_serialize(
49                        {
50                            "exc_type": exc_type,
51                            "exc_value": exc_value,
52                            "exc_traceback": exc_traceback,
53                        }
54                    )
55                )
56            )
57            return False
58        return True

class WritableStream(typing.Protocol):
11class WritableStream(Protocol):
12    """Protocol for objects that support write operations."""
13
14    def write(self, __s: str) -> int: ...

Protocol for objects that support write operations.

WritableStream(*args, **kwargs)
1945def _no_init_or_replace_init(self, *args, **kwargs):
1946    cls = type(self)
1947
1948    if cls._is_protocol:
1949        raise TypeError('Protocols cannot be instantiated')
1950
1951    # Already using a custom `__init__`. No need to calculate correct
1952    # `__init__` to call. This can lead to RecursionError. See bpo-45121.
1953    if cls.__init__ is not _no_init_or_replace_init:
1954        return
1955
1956    # Initially, `__init__` of a protocol subclass is set to `_no_init_or_replace_init`.
1957    # The first instantiation of the subclass will call `_no_init_or_replace_init` which
1958    # searches for a proper new `__init__` in the MRO. The new `__init__`
1959    # replaces the subclass' old `__init__` (ie `_no_init_or_replace_init`). Subsequent
1960    # instantiation of the protocol subclass will thus use the new
1961    # `__init__` and no longer call `_no_init_or_replace_init`.
1962    for base in cls.__mro__:
1963        init = base.__dict__.get('__init__', _no_init_or_replace_init)
1964        if init is not _no_init_or_replace_init:
1965            cls.__init__ = init
1966            break
1967    else:
1968        # should not happen
1969        cls.__init__ = object.__init__
1970
1971    cls.__init__(self, *args, **kwargs)
def write(self, _WritableStream__s: str) -> int:
14    def write(self, __s: str) -> int: ...
class ExceptionContext:
17class ExceptionContext:
18    """context manager which catches all exceptions happening while the context is open, `.write()` the exception trace to the given stream, and then raises the exception
19
20
21    for example:
22
23    ```python
24    errorfile = open('error.log', 'w')
25
26    with ExceptionContext(errorfile):
27            # do something that might throw an exception
28            # if it does, the exception trace will be written to errorfile
29            # and then the exception will be raised
30    ```
31
32    """
33
34    def __init__(self, stream: WritableStream) -> None:
35        self.stream: WritableStream = stream
36
37    def __enter__(self) -> ExceptionContext:
38        return self
39
40    def __exit__(
41        self,
42        exc_type: type[BaseException] | None,
43        exc_value: BaseException | None,
44        exc_traceback: TracebackType | None,
45    ) -> bool:
46        if exc_type is not None:
47            self.stream.write(
48                json.dumps(
49                    json_serialize(
50                        {
51                            "exc_type": exc_type,
52                            "exc_value": exc_value,
53                            "exc_traceback": exc_traceback,
54                        }
55                    )
56                )
57            )
58            return False
59        return True

context manager which catches all exceptions happening while the context is open, .write() the exception trace to the given stream, and then raises the exception

for example:

errorfile = open('error.log', 'w')

with ExceptionContext(errorfile):
        # do something that might throw an exception
        # if it does, the exception trace will be written to errorfile
        # and then the exception will be raised
ExceptionContext(stream: WritableStream)
34    def __init__(self, stream: WritableStream) -> None:
35        self.stream: WritableStream = stream
stream: WritableStream