bear-utils 0.0.1__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.
Files changed (107) hide show
  1. bear_utils/__init__.py +51 -0
  2. bear_utils/__main__.py +14 -0
  3. bear_utils/_internal/__init__.py +0 -0
  4. bear_utils/_internal/_version.py +1 -0
  5. bear_utils/_internal/cli.py +119 -0
  6. bear_utils/_internal/debug.py +174 -0
  7. bear_utils/ai/__init__.py +30 -0
  8. bear_utils/ai/ai_helpers/__init__.py +136 -0
  9. bear_utils/ai/ai_helpers/_common.py +19 -0
  10. bear_utils/ai/ai_helpers/_config.py +24 -0
  11. bear_utils/ai/ai_helpers/_parsers.py +194 -0
  12. bear_utils/ai/ai_helpers/_types.py +15 -0
  13. bear_utils/cache/__init__.py +131 -0
  14. bear_utils/cli/__init__.py +22 -0
  15. bear_utils/cli/_args.py +12 -0
  16. bear_utils/cli/_get_version.py +207 -0
  17. bear_utils/cli/commands.py +105 -0
  18. bear_utils/cli/prompt_helpers.py +186 -0
  19. bear_utils/cli/shell/__init__.py +1 -0
  20. bear_utils/cli/shell/_base_command.py +81 -0
  21. bear_utils/cli/shell/_base_shell.py +430 -0
  22. bear_utils/cli/shell/_common.py +19 -0
  23. bear_utils/cli/typer_bridge.py +90 -0
  24. bear_utils/config/__init__.py +13 -0
  25. bear_utils/config/config_manager.py +229 -0
  26. bear_utils/config/dir_manager.py +69 -0
  27. bear_utils/config/settings_manager.py +179 -0
  28. bear_utils/constants/__init__.py +90 -0
  29. bear_utils/constants/_exceptions.py +8 -0
  30. bear_utils/constants/_exit_code.py +60 -0
  31. bear_utils/constants/_http_status_code.py +37 -0
  32. bear_utils/constants/_lazy_typing.py +15 -0
  33. bear_utils/constants/_meta.py +196 -0
  34. bear_utils/constants/date_related.py +25 -0
  35. bear_utils/constants/time_related.py +24 -0
  36. bear_utils/database/__init__.py +8 -0
  37. bear_utils/database/_db_manager.py +98 -0
  38. bear_utils/events/__init__.py +18 -0
  39. bear_utils/events/events_class.py +52 -0
  40. bear_utils/events/events_module.py +74 -0
  41. bear_utils/extras/__init__.py +28 -0
  42. bear_utils/extras/_async_helpers.py +67 -0
  43. bear_utils/extras/_tools.py +185 -0
  44. bear_utils/extras/_zapper.py +399 -0
  45. bear_utils/extras/platform_utils.py +57 -0
  46. bear_utils/extras/responses/__init__.py +5 -0
  47. bear_utils/extras/responses/function_response.py +451 -0
  48. bear_utils/extras/wrappers/__init__.py +1 -0
  49. bear_utils/extras/wrappers/add_methods.py +100 -0
  50. bear_utils/extras/wrappers/string_io.py +46 -0
  51. bear_utils/files/__init__.py +6 -0
  52. bear_utils/files/file_handlers/__init__.py +5 -0
  53. bear_utils/files/file_handlers/_base_file_handler.py +107 -0
  54. bear_utils/files/file_handlers/file_handler_factory.py +280 -0
  55. bear_utils/files/file_handlers/json_file_handler.py +71 -0
  56. bear_utils/files/file_handlers/log_file_handler.py +40 -0
  57. bear_utils/files/file_handlers/toml_file_handler.py +76 -0
  58. bear_utils/files/file_handlers/txt_file_handler.py +76 -0
  59. bear_utils/files/file_handlers/yaml_file_handler.py +64 -0
  60. bear_utils/files/ignore_parser.py +293 -0
  61. bear_utils/graphics/__init__.py +6 -0
  62. bear_utils/graphics/bear_gradient.py +145 -0
  63. bear_utils/graphics/font/__init__.py +13 -0
  64. bear_utils/graphics/font/_raw_block_letters.py +463 -0
  65. bear_utils/graphics/font/_theme.py +31 -0
  66. bear_utils/graphics/font/_utils.py +220 -0
  67. bear_utils/graphics/font/block_font.py +192 -0
  68. bear_utils/graphics/font/glitch_font.py +63 -0
  69. bear_utils/graphics/image_helpers.py +45 -0
  70. bear_utils/gui/__init__.py +8 -0
  71. bear_utils/gui/gui_tools/__init__.py +10 -0
  72. bear_utils/gui/gui_tools/_settings.py +36 -0
  73. bear_utils/gui/gui_tools/_types.py +12 -0
  74. bear_utils/gui/gui_tools/qt_app.py +150 -0
  75. bear_utils/gui/gui_tools/qt_color_picker.py +130 -0
  76. bear_utils/gui/gui_tools/qt_file_handler.py +130 -0
  77. bear_utils/gui/gui_tools/qt_input_dialog.py +303 -0
  78. bear_utils/logger_manager/__init__.py +109 -0
  79. bear_utils/logger_manager/_common.py +63 -0
  80. bear_utils/logger_manager/_console_junk.py +135 -0
  81. bear_utils/logger_manager/_log_level.py +50 -0
  82. bear_utils/logger_manager/_styles.py +95 -0
  83. bear_utils/logger_manager/logger_protocol.py +42 -0
  84. bear_utils/logger_manager/loggers/__init__.py +1 -0
  85. bear_utils/logger_manager/loggers/_console.py +223 -0
  86. bear_utils/logger_manager/loggers/_level_sin.py +61 -0
  87. bear_utils/logger_manager/loggers/_logger.py +19 -0
  88. bear_utils/logger_manager/loggers/base_logger.py +244 -0
  89. bear_utils/logger_manager/loggers/base_logger.pyi +51 -0
  90. bear_utils/logger_manager/loggers/basic_logger/__init__.py +5 -0
  91. bear_utils/logger_manager/loggers/basic_logger/logger.py +80 -0
  92. bear_utils/logger_manager/loggers/basic_logger/logger.pyi +19 -0
  93. bear_utils/logger_manager/loggers/buffer_logger.py +57 -0
  94. bear_utils/logger_manager/loggers/console_logger.py +278 -0
  95. bear_utils/logger_manager/loggers/console_logger.pyi +50 -0
  96. bear_utils/logger_manager/loggers/fastapi_logger.py +333 -0
  97. bear_utils/logger_manager/loggers/file_logger.py +151 -0
  98. bear_utils/logger_manager/loggers/simple_logger.py +98 -0
  99. bear_utils/logger_manager/loggers/sub_logger.py +105 -0
  100. bear_utils/logger_manager/loggers/sub_logger.pyi +23 -0
  101. bear_utils/monitoring/__init__.py +13 -0
  102. bear_utils/monitoring/_common.py +28 -0
  103. bear_utils/monitoring/host_monitor.py +346 -0
  104. bear_utils/time/__init__.py +59 -0
  105. bear_utils-0.0.1.dist-info/METADATA +305 -0
  106. bear_utils-0.0.1.dist-info/RECORD +107 -0
  107. bear_utils-0.0.1.dist-info/WHEEL +4 -0
@@ -0,0 +1,244 @@
1
+ """BaseLogger: A comprehensive console logger that is the foundation for all other loggers."""
2
+
3
+ from functools import partial
4
+ from io import StringIO
5
+ import sys
6
+ from typing import Any, Self
7
+
8
+ from prompt_toolkit.formatted_text import ANSI, FormattedText, to_formatted_text
9
+ from prompt_toolkit.shortcuts import print_formatted_text
10
+ from rich.text import Text
11
+ from rich.theme import Theme
12
+ from rich.traceback import Traceback
13
+ from singleton_base import SingletonBase
14
+
15
+ from bear_utils.logger_manager._common import ExecValues, StackLevelTracker
16
+ from bear_utils.logger_manager._styles import DEFAULT_THEME, LOGGER_METHODS, LoggerExtraInfo
17
+ from bear_utils.logger_manager.loggers._console import LogConsole
18
+
19
+ from ._level_sin import INFO, add_level_name, check_level, lvl_exists
20
+ from .sub_logger import SubConsoleLogger
21
+
22
+ # TODO: Needs some work since this is so tightly coupled with the ConsoleLogger
23
+
24
+
25
+ class BaseLogger(SingletonBase):
26
+ """BaseLogger: A comprehensive console logger that is the foundation for all other loggers."""
27
+
28
+ def __init__(
29
+ self,
30
+ output_handler: Any = None,
31
+ theme: Theme | None = None,
32
+ style_disabled: bool = False,
33
+ logger_mode: bool = False,
34
+ **kwargs,
35
+ ) -> None:
36
+ """Initialize the BaseLogger with an optional style_disabled flag.
37
+
38
+ This flag can be used to disable styled output in the logger.
39
+ """
40
+ self.output_handler = output_handler or self._default_output
41
+ self._level: int = kwargs.get("level", INFO)
42
+ self.stack_tracker: StackLevelTracker = StackLevelTracker()
43
+ self.logger_mode: bool = logger_mode
44
+ self.theme: Theme = DEFAULT_THEME if theme is None else theme
45
+ self.style_disabled: bool = style_disabled
46
+ self.console: LogConsole[StringIO] = self.get_console(self.theme, style_disabled)
47
+ self.console_buffer: StringIO = self.console.file
48
+ self.backup_console = LogConsole(theme=self.theme, highlight=True, force_terminal=True)
49
+ self._generate_style_methods()
50
+
51
+ @staticmethod
52
+ def get_console(theme: Theme, style_disabled: bool) -> LogConsole:
53
+ """Create and return a Console instance with the specified theme and styling options."""
54
+ if style_disabled:
55
+ console = LogConsole(
56
+ file=StringIO(),
57
+ highlight=False,
58
+ force_terminal=True,
59
+ style=None, # Disable styling
60
+ )
61
+ else:
62
+ console: LogConsole = LogConsole(
63
+ file=StringIO(),
64
+ highlight=False,
65
+ force_terminal=True,
66
+ color_system="truecolor",
67
+ theme=theme,
68
+ )
69
+ return console
70
+
71
+ def _default_output(self, msg: object, _: LoggerExtraInfo, *args, **kwargs) -> None:
72
+ """Default output handler that prints to console."""
73
+ if not self.logger_mode:
74
+ self.print(msg, *args, **kwargs)
75
+
76
+ def __enter__(self) -> Self:
77
+ """Enter the context manager, returning the ConsoleLogger instance.
78
+
79
+ This allows for using the logger in a with statement.
80
+ """
81
+ return self
82
+
83
+ def __exit__(self, exc_type: object, exc_value: object, traceback: object) -> None:
84
+ """Exit the context manager, cleaning up resources.
85
+
86
+ This is called when the with statement is exited.
87
+ """
88
+ self.exit()
89
+
90
+ def trigger_buffer_flush(self) -> str | Text:
91
+ """Flush buffered messages to console output."""
92
+ return "No buffering handler available."
93
+
94
+ def set_base_level(self, level: int | str) -> None:
95
+ """Set the logging level for the console.
96
+
97
+ This method allows changing the logging level dynamically.
98
+
99
+ This isn't actually a logging logger so we are having to add this while avoiding messing with
100
+ any subclasses that do subclass Logger.
101
+
102
+ Args:
103
+ level (int): The logging level to set. This should be a valid logging level constant.
104
+ """
105
+ self._level = check_level(level)
106
+
107
+ def filter_by_level(self, level: str | int) -> bool:
108
+ """Filter method to determine if a message should be logged based on its level.
109
+
110
+ This method checks if the provided level is greater than or equal to the logger's level.
111
+
112
+ Args:
113
+ level (int): The logging level of the message.
114
+
115
+ Returns:
116
+ bool: True if the message should be logged, False otherwise.
117
+ """
118
+ level = check_level(level)
119
+ return level >= self._level
120
+
121
+ def get_sub_logger(self, namespace: str, **kwargs) -> "SubConsoleLogger":
122
+ """Get a sub-logger with a specific namespace."""
123
+ return SubConsoleLogger(self, namespace, **kwargs) # type: ignore[return-value]
124
+
125
+ def _generate_style_methods(self) -> None:
126
+ """Generate dynamic logging methods with proper log level registration."""
127
+ for style_name, extra in LOGGER_METHODS.items():
128
+ if not lvl_exists(extra["log_level"]): # I'd rather if things crash than silently fail
129
+ add_level_name(extra["log_level"], extra.get("style_name"))
130
+ setattr(self, style_name, partial(self.replacement_method, injected_extra=extra.copy()))
131
+
132
+ def replacement_method(self, msg: object, *args, **kwargs) -> None:
133
+ """Replacement method for logging messages with additional context."""
134
+ if self.stack_tracker.not_set:
135
+ self.stack_tracker.record_start()
136
+ filter_func = kwargs.pop("filter_func", self.filter_by_level)
137
+ extra: LoggerExtraInfo = kwargs.pop("injected_extra") | kwargs.pop("extra", {})
138
+ kwargs["style"] = extra.pop("style", None)
139
+ if extra.get("namespace"):
140
+ msg = f"<{extra.get('namespace')}> {msg}"
141
+ if filter_func(extra.get("log_level", self._level)):
142
+ self.output_handler(msg, extra, *args, **kwargs)
143
+
144
+ def print(
145
+ self,
146
+ msg: object,
147
+ end: str = "\n",
148
+ exc_info: object | None = None,
149
+ extra: dict | None = None,
150
+ *_,
151
+ **kwargs,
152
+ ) -> None | str:
153
+ """Print a message to the console with the specified formatting.
154
+
155
+ This method allows for printing messages with additional context and formatting.
156
+ """
157
+ if exc_info is not None:
158
+ try:
159
+ exception: Traceback = self._get_exception(manual=True)
160
+ self._print(exception, end=end, **kwargs)
161
+ except Exception as e:
162
+ print(
163
+ f"ConsoleLogger: Error printing exception traceback. Message: {msg} Exception: {exc_info} Error: {e}"
164
+ )
165
+ self._print(msg, end, style=kwargs.pop("style", None))
166
+ if extra:
167
+ self._print(msg=extra, end=end, json=True, indent=4)
168
+
169
+ def print_json(
170
+ self,
171
+ json: str | None = None,
172
+ data: dict | None = None,
173
+ indent: int = 2,
174
+ sort: bool = False,
175
+ **kwargs,
176
+ ) -> None:
177
+ """Just a pass-through to the console.print_json method."""
178
+ self.console.print_json(json=json, data=data, indent=indent, sort_keys=sort, **kwargs)
179
+
180
+ def raw_print(self, msg: object, end: str = "\n", *_, **kwargs) -> None:
181
+ """Use the underlying console directly and bypass all the extra formatting and handling.
182
+
183
+ Args:
184
+ msg (object): The message to print.
185
+ end (str, optional): The string appended after the message. Defaults to new line.
186
+ """
187
+ self.backup_console.print(msg, end=end, style=kwargs.pop("style", "white"), **kwargs)
188
+
189
+ def _print(self, msg: object, end: str, json: bool = False, *args, **kwargs) -> None:
190
+ """Print a message to the console with the specified formatting.
191
+
192
+ This method allows for printing messages with additional context and formatting.
193
+ """
194
+ try:
195
+ if json:
196
+ self.print_json(msg, *args, **kwargs) # type: ignore[arg-type]
197
+ else:
198
+ self.console.print(msg, end="", style=kwargs.pop("style", "white"))
199
+ formatted_text: FormattedText = to_formatted_text(ANSI(self.console_buffer.getvalue()))
200
+ print_formatted_text(formatted_text, end=end)
201
+ self._reset_buffer()
202
+ except Exception as e:
203
+ print(
204
+ f"{self.__class__.__name__.upper()}: Error printing message. Message: {msg} Exception: {e}. "
205
+ "Please check the console buffer for more details."
206
+ )
207
+ self._reset_buffer()
208
+
209
+ def _extract_exception_values(self, exc_info: Any) -> ExecValues | None:
210
+ """Extract exception values in a clean, reusable way."""
211
+ if isinstance(exc_info, BaseException):
212
+ exc_tuple = (type(exc_info), exc_info, exc_info.__traceback__)
213
+ elif exc_info is True:
214
+ exc_tuple = sys.exc_info()
215
+ else:
216
+ exc_tuple = exc_info
217
+ if exc_tuple:
218
+ exc_type, exc_value, exc_traceback = exc_tuple
219
+ if exc_type is not None and exc_value is not None and exc_traceback is not None:
220
+ return {"exc_type": exc_type, "exc_value": exc_value, "exc_traceback": exc_traceback}
221
+ return None
222
+
223
+ def _get_exception(self, manual: bool = False, exec_values: ExecValues | None = None) -> Traceback:
224
+ if manual and exec_values:
225
+ return Traceback.from_exception(
226
+ exc_type=exec_values["exc_type"],
227
+ exc_value=exec_values["exc_value"],
228
+ traceback=exec_values["exc_traceback"],
229
+ show_locals=True,
230
+ width=100,
231
+ )
232
+ return Traceback(show_locals=True, width=100)
233
+
234
+ def _reset_buffer(self) -> None:
235
+ """Reset the console buffer."""
236
+ self.console_buffer.truncate(0)
237
+ self.console_buffer.seek(0)
238
+
239
+ def exit(self) -> None:
240
+ """Exit the console logger.
241
+
242
+ This method is called when the program exits to clean up resources.
243
+ """
244
+ self.console_buffer.close()
@@ -0,0 +1,51 @@
1
+ from io import StringIO
2
+ from typing import Any, Self
3
+
4
+ from rich.console import Console
5
+ from rich.text import Text
6
+ from rich.theme import Theme
7
+ from rich.traceback import Traceback
8
+ from singleton_base import SingletonBase
9
+
10
+ from bear_utils.logger_manager._common import ExecValues, StackLevelTracker
11
+
12
+ from .sub_logger import SubConsoleLogger
13
+
14
+ class BaseLogger(SingletonBase):
15
+ output_handler: Any
16
+ stack_tracker: StackLevelTracker
17
+ theme: Theme
18
+ _level: int
19
+ style_disabled: bool
20
+ console: Console
21
+ console_buffer: StringIO
22
+ logger_mode: bool
23
+ sub_logger: dict[str, SubConsoleLogger]
24
+ # fmt: off
25
+ def __init__(self, output_handler: Any = None, theme: Theme | None = ..., style_disabled: bool = ..., logger_mode: bool = ..., **kwargs) -> None: ...
26
+ @staticmethod
27
+ def get_console(theme: Theme, style_disabled: bool) -> Console: ...
28
+ def __enter__(self) -> Self: ...
29
+ def __exit__(self, exc_type: object, exc_value: object, traceback: object) -> None: ...
30
+ def _generate_style_methods(self, **kwargs) -> None: ...
31
+ def get_sub_logger(self, namespace: str, **kwargs: Any) -> SubConsoleLogger: ...
32
+ def replacement_method(self, msg: object, *args: Any, **kwargs: Any) -> None: ...
33
+ def print(self, msg: object, end: str="\n", exc_info:str|None=None, extra: dict | None = None, *args, **kwargs) -> None | str: ...
34
+ def print_json(self, data: Any | None = ..., indent: int = ..., sort: bool = ...) -> None: ...
35
+ def set_base_level(self, level: int) -> None: ...
36
+ def filter_by_level(self, level: int) -> bool: ...
37
+ def trigger_buffer_flush(self) -> str | Text: ...
38
+ def _print(self, msg: object, end: str, json: bool = ..., *args: Any, **kwargs: Any) -> None: ...
39
+ def _get_exception(self, manual: bool = ..., exec_values: ExecValues | None = ...) -> Traceback: ...
40
+ def _extract_exception_values(self, exc_info: str | None) -> ExecValues | None: ...
41
+ def _reset_buffer(self) -> None: ...
42
+ def exit(self) -> None: ...
43
+ def debug(self, msg: object, *args: Any, **kwargs: Any) -> None: ...
44
+ def info(self, msg: object, *args: Any, **kwargs: Any) -> None: ...
45
+ def exception(self, msg: object, *args: Any, **kwargs: Any) -> None: ...
46
+ def warning(self, msg: object, *args: Any, **kwargs: Any) -> None: ...
47
+ def error(self, msg: object, *args: Any, **kwargs: Any) -> None: ...
48
+ def critical(self, msg: object, *args: Any, **kwargs: Any) -> None: ...
49
+ def success(self, msg: object, *args: Any, **kwargs: Any) -> None: ...
50
+ def failure(self, msg: object, *args: Any, **kwargs: Any) -> None: ...
51
+ def verbose(self, msg: object, *args: Any, **kwargs: Any) -> None: ...
@@ -0,0 +1,5 @@
1
+ """A basic logger to have around just in case the user doesn't already have one."""
2
+
3
+ from .logger import BasicLogger
4
+
5
+ __all__ = ["BasicLogger"]
@@ -0,0 +1,80 @@
1
+ """Basic logger using the Rich library."""
2
+
3
+ from collections.abc import Callable
4
+
5
+ from rich import inspect
6
+ from rich.console import Console
7
+ from rich.theme import Theme
8
+
9
+ THEME: dict[str, str] = {
10
+ "info": "dim green",
11
+ "debug": "bold blue",
12
+ "warning": "bold yellow",
13
+ "error": "bold red",
14
+ "exception": "bold red",
15
+ "success": "bold green",
16
+ "failure": "bold red underline",
17
+ "verbose": "bold blue",
18
+ }
19
+
20
+
21
+ class BasicLogger:
22
+ """A basic logger that uses the Rich library to print messages to the console."""
23
+
24
+ def __init__(self) -> None:
25
+ """Initialize the BasicLogger with a Rich Console instance."""
26
+ self.console = Console(theme=Theme(THEME))
27
+ for level in THEME:
28
+ method = self.replacement_method(level)
29
+ setattr(self, level, method)
30
+
31
+ def replacement_method(self, level: str) -> Callable:
32
+ """Create a method that logs messages at the specified level."""
33
+
34
+ def method(msg: object, **kwargs) -> None:
35
+ """Log a message at the specified level with the given style.
36
+
37
+ Args:
38
+ msg (object): The message to log.
39
+ **kwargs: Additional keyword arguments for formatting.
40
+ """
41
+ self.log(level, msg, **kwargs)
42
+
43
+ return method
44
+
45
+ def log(self, level: str, msg: object, **kwargs) -> None:
46
+ """Log a message at the specified level.
47
+
48
+ Args:
49
+ level (str): The logging level (e.g., 'info', 'debug', 'warning', etc.).
50
+ msg (object): The message to log.
51
+ **kwargs: Additional keyword arguments for formatting.
52
+ """
53
+ self.console.print(msg, style=level, **kwargs)
54
+
55
+ def print(self, msg: object, **kwargs) -> None:
56
+ """Print a message to the console with the specified style.
57
+
58
+ Args:
59
+ msg (object): The message to print.
60
+ **kwargs: Additional keyword arguments for formatting.
61
+ """
62
+ self.console.print(msg, **kwargs)
63
+
64
+ def inspect(self, obj: object, **kwargs) -> None:
65
+ """Inspect an object and print its details to the console.
66
+
67
+ Args:
68
+ obj (object): The object to inspect.
69
+ **kwargs: Additional keyword arguments for formatting.
70
+ """
71
+ inspect(obj, console=self.console, **kwargs)
72
+
73
+ def print_json(self, data: object, **kwargs) -> None:
74
+ """Print a JSON object to the console.
75
+
76
+ Args:
77
+ data (object): The JSON data to print.
78
+ **kwargs: Additional keyword arguments for formatting.
79
+ """
80
+ self.console.print_json(data=data, **kwargs)
@@ -0,0 +1,19 @@
1
+ from collections.abc import Callable
2
+
3
+ from rich.console import Console
4
+
5
+ class BasicLogger:
6
+ def __init__(self, console: Console | None = None) -> None: ...
7
+ def info(self, msg: object, **kwargs) -> None: ...
8
+ def debug(self, msg: object, **kwargs) -> None: ...
9
+ def warning(self, msg: object, **kwargs) -> None: ...
10
+ def error(self, msg: object, **kwargs) -> None: ...
11
+ def exception(self, msg: object, **kwargs) -> None: ...
12
+ def success(self, msg: object, **kwargs) -> None: ...
13
+ def failure(self, msg: object, **kwargs) -> None: ...
14
+ def verbose(self, msg: object, **kwargs) -> None: ...
15
+ def print(self, msg: object, style: str | None = None, **kwargs) -> None: ...
16
+ def log(self, level: str, msg: object, **kwargs) -> None: ...
17
+ def inspect(self, obj: object, **kwargs) -> None: ...
18
+ def print_json(self, data: object, **kwargs) -> None: ...
19
+ def replacement_method(self, level: str) -> Callable: ...
@@ -0,0 +1,57 @@
1
+ """BufferLogger: A buffer-based logger that writes styled log messages to a buffer for later retrieval."""
2
+
3
+ from logging import DEBUG
4
+ from typing import Any, override
5
+
6
+ from rich.theme import Theme
7
+
8
+ from .console_logger import ConsoleLogger
9
+ from .sub_logger import SubConsoleLogger
10
+
11
+
12
+ class BufferLogger(ConsoleLogger):
13
+ """A buffer-based logger that writes styled log messages to a buffer.
14
+
15
+ Combines Python's logging framework with Rich console styling, but outputs
16
+ to a buffer instead of console or file. Supports buffering of log messages,
17
+
18
+ Features:
19
+ - Buffering of log messages
20
+ - Rich-style method generation (info, error, debug, etc.)
21
+ - Consistent print() interface
22
+ - Exception tracebacks in buffer format
23
+
24
+ Example:
25
+ logger = BufferLogger.get_instance(
26
+ init=True,
27
+ name="BufferLogger",
28
+ )
29
+ logger.info("This goes to the buffer")
30
+ logger.error("This error is logged to buffer")
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ theme: Theme | None = None,
36
+ name: str = "BufferLogger",
37
+ level: int = DEBUG,
38
+ *_,
39
+ **kwargs,
40
+ ) -> None:
41
+ """Initialize the BufferLogger with buffering settings."""
42
+ ConsoleLogger.__init__(
43
+ self,
44
+ name=name,
45
+ level=level,
46
+ file=False,
47
+ console=False,
48
+ buffering=True,
49
+ queue_handler=kwargs.pop("queue_handler", False),
50
+ theme=theme,
51
+ logger_mode=True,
52
+ **kwargs,
53
+ )
54
+
55
+ @override
56
+ def get_sub_logger(self, namespace: str, **kwargs: Any) -> SubConsoleLogger:
57
+ return SubConsoleLogger(self, namespace, **kwargs)