SwiftGUI_Logging 0.1.3__tar.gz → 0.1.4__tar.gz
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.
- {swiftgui_logging-0.1.3 → swiftgui_logging-0.1.4}/PKG-INFO +1 -1
- {swiftgui_logging-0.1.3 → swiftgui_logging-0.1.4}/pyproject.toml +1 -1
- {swiftgui_logging-0.1.3 → swiftgui_logging-0.1.4}/src/SwiftGUI_Logging/Configs/ExceptionLogging.py +15 -1
- {swiftgui_logging-0.1.3 → swiftgui_logging-0.1.4}/src/SwiftGUI_Logging/ExceptionHandling.py +39 -4
- {swiftgui_logging-0.1.3 → swiftgui_logging-0.1.4}/src/SwiftGUI_Logging/MemoryHandlerRotatingBuffer.py +3 -11
- {swiftgui_logging-0.1.3 → swiftgui_logging-0.1.4}/LICENSE +0 -0
- {swiftgui_logging-0.1.3 → swiftgui_logging-0.1.4}/README.md +0 -0
- {swiftgui_logging-0.1.3 → swiftgui_logging-0.1.4}/src/SwiftGUI_Logging/Configs/__init__.py +0 -0
- {swiftgui_logging-0.1.3 → swiftgui_logging-0.1.4}/src/SwiftGUI_Logging/Utils.py +0 -0
- {swiftgui_logging-0.1.3 → swiftgui_logging-0.1.4}/src/SwiftGUI_Logging/__init__.py +0 -0
{swiftgui_logging-0.1.3 → swiftgui_logging-0.1.4}/src/SwiftGUI_Logging/Configs/ExceptionLogging.py
RENAMED
|
@@ -11,6 +11,9 @@ def exceptions_to_file(
|
|
|
11
11
|
buffer_size: int = 5000,
|
|
12
12
|
trigger_level: int = logging.ERROR,
|
|
13
13
|
log_level: int = logging.DEBUG,
|
|
14
|
+
include_main_thread: bool = True,
|
|
15
|
+
include_threads: bool = True,
|
|
16
|
+
include_tkinter: bool = True,
|
|
14
17
|
reraise: bool = False,
|
|
15
18
|
datetime_format: str = "_%Y-%m-%d_%H-%M-%S",
|
|
16
19
|
formatter_format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
@@ -29,6 +32,9 @@ def exceptions_to_file(
|
|
|
29
32
|
:param buffer_size: How many reports are saved before the first ones are overritten again
|
|
30
33
|
:param trigger_level: Level at which the exceptions are treated. Reports at and above this level trigger a file-write
|
|
31
34
|
:param log_level: Logs below this level are ignored and not written to the file
|
|
35
|
+
:param include_main_thread: True, if the "normal thread's" exceptions should be caught
|
|
36
|
+
:param include_threads: True, if Thread-exceptions should be caught too
|
|
37
|
+
:param include_tkinter: True, if Tkinter-exceptions should be caught too
|
|
32
38
|
:param reraise: True, if the exception should still be raised, even though it was logged. Good for debugging purposes
|
|
33
39
|
:param datetime_format: Format of the timestamp that extends the filename
|
|
34
40
|
:param formatter_format: Format of the log-entries in the file
|
|
@@ -71,5 +77,13 @@ def exceptions_to_file(
|
|
|
71
77
|
|
|
72
78
|
logger.addHandler(buffer_handler)
|
|
73
79
|
|
|
74
|
-
sgl.reroute_exceptions(
|
|
80
|
+
sgl.reroute_exceptions(
|
|
81
|
+
logger,
|
|
82
|
+
reraise=reraise,
|
|
83
|
+
loglevel=trigger_level,
|
|
84
|
+
pass_text_to_function=exception_occured,
|
|
85
|
+
include_main_thread=include_main_thread,
|
|
86
|
+
include_threads=include_threads,
|
|
87
|
+
include_tkinter=include_tkinter,
|
|
88
|
+
)
|
|
75
89
|
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import logging.handlers
|
|
2
|
+
import threading
|
|
2
3
|
import traceback
|
|
3
4
|
import sys
|
|
4
5
|
from typing import Callable, Any
|
|
5
6
|
|
|
7
|
+
try:
|
|
8
|
+
import tkinter as tk
|
|
9
|
+
except ImportError:
|
|
10
|
+
tk = None
|
|
6
11
|
|
|
7
12
|
def reroute_exceptions(
|
|
8
13
|
logger: logging.Logger = logging.getLogger(),
|
|
@@ -10,6 +15,9 @@ def reroute_exceptions(
|
|
|
10
15
|
*,
|
|
11
16
|
logger_warnings: logging.Logger = None,
|
|
12
17
|
loglevel_warnings: int = logging.WARNING,
|
|
18
|
+
include_main_thread: bool = True,
|
|
19
|
+
include_threads: bool = True,
|
|
20
|
+
include_tkinter: bool = True,
|
|
13
21
|
reraise: bool = False,
|
|
14
22
|
print_to_console: bool = False,
|
|
15
23
|
pass_text_to_function: Callable[[str], Any] = None,
|
|
@@ -21,7 +29,10 @@ def reroute_exceptions(
|
|
|
21
29
|
:param loglevel: The loglevel for EXCEPTIONS
|
|
22
30
|
:param logger_warnings: The logger where WARNINGS go
|
|
23
31
|
:param loglevel_warnings: The level of logging for WARNINGS
|
|
24
|
-
:param reraise: True, if the exception should be raised again
|
|
32
|
+
:param reraise: True, if the exception should be raised again. THIS DOESN'T WORK FOR THREAD EXCEPTIONS!
|
|
33
|
+
:param include_main_thread: True, if the "normal thread's" exceptions should be caught
|
|
34
|
+
:param include_threads: True, if Thread-exceptions should be caught too
|
|
35
|
+
:param include_tkinter: True, if Tkinter-exceptions should be caught too
|
|
25
36
|
:param pass_text_to_function: Pass a function/method and the exception-text is passed to it
|
|
26
37
|
:param print_to_console: True, if the text should be printed to the console using print(...)
|
|
27
38
|
:return:
|
|
@@ -32,8 +43,8 @@ def reroute_exceptions(
|
|
|
32
43
|
if loglevel_warnings is None:
|
|
33
44
|
loglevel_warnings = loglevel
|
|
34
45
|
|
|
35
|
-
def catch(exctype, value, tb):
|
|
36
|
-
text = "".join(traceback.format_exception(exctype, value, tb))
|
|
46
|
+
def catch(exctype, value, tb, additional_text: str = ""):
|
|
47
|
+
text = additional_text + "".join(traceback.format_exception(exctype, value, tb))
|
|
37
48
|
|
|
38
49
|
if issubclass(exctype, Warning): # Warnings
|
|
39
50
|
if logger_warnings is not None:
|
|
@@ -58,7 +69,31 @@ def reroute_exceptions(
|
|
|
58
69
|
if print_to_console:
|
|
59
70
|
print(text)
|
|
60
71
|
|
|
72
|
+
def catch_normal(exctype, value, tb):
|
|
73
|
+
catch(exctype, value, tb)
|
|
61
74
|
if reraise:
|
|
62
75
|
sys.__excepthook__(exctype, value, tb)
|
|
63
76
|
|
|
64
|
-
|
|
77
|
+
def catch_thread(exc: threading.ExceptHookArgs):
|
|
78
|
+
catch(exc.exc_type, exc.exc_value, exc.exc_traceback, f"On thread {exc.thread}:\n")
|
|
79
|
+
|
|
80
|
+
if include_main_thread:
|
|
81
|
+
sys.excepthook = catch_normal
|
|
82
|
+
|
|
83
|
+
if include_threads:
|
|
84
|
+
threading.excepthook = catch_thread
|
|
85
|
+
|
|
86
|
+
if include_tkinter and tk is not None:
|
|
87
|
+
# Catch tkinter exceptions
|
|
88
|
+
actual_callback = tk.Tk.report_callback_exception
|
|
89
|
+
def catch_tkinter(self, exctype, value, tb):
|
|
90
|
+
catch(exctype, value, tb, additional_text="Tkinter exception:\n")
|
|
91
|
+
|
|
92
|
+
if reraise:
|
|
93
|
+
actual_callback(self, exctype, value, tb) # I know this shows warnings, but it works
|
|
94
|
+
|
|
95
|
+
tk.Tk.report_callback_exception = catch_tkinter
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
@@ -20,7 +20,6 @@ class MemoryHandlerRotatingBuffer(logging.handlers.MemoryHandler):
|
|
|
20
20
|
"""
|
|
21
21
|
super().__init__(capacity, flushLevel, target, flushOnClose=False)
|
|
22
22
|
self.call_after_flushing = call_after_flushing if call_after_flushing else lambda *_:_
|
|
23
|
-
self._should_flush = False
|
|
24
23
|
|
|
25
24
|
def shouldFlush(self, record):
|
|
26
25
|
"""
|
|
@@ -31,17 +30,10 @@ class MemoryHandlerRotatingBuffer(logging.handlers.MemoryHandler):
|
|
|
31
30
|
if len(self.buffer) > self.capacity: # Remove 0th element so the buffer doesn't "overflow"
|
|
32
31
|
self.buffer.pop(0)
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
self._should_flush = True
|
|
36
|
-
return True
|
|
37
|
-
|
|
38
|
-
return False
|
|
33
|
+
return record.levelno >= self.flushLevel
|
|
39
34
|
|
|
40
35
|
def flush(self):
|
|
41
|
-
super().flush()
|
|
42
|
-
|
|
43
|
-
if self._should_flush:
|
|
44
|
-
self.call_after_flushing()
|
|
45
|
-
self._should_flush = False
|
|
36
|
+
super().flush()
|
|
37
|
+
self.call_after_flushing()
|
|
46
38
|
|
|
47
39
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|