bear-utils 0.7.11__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 (83) hide show
  1. bear_utils/__init__.py +13 -0
  2. bear_utils/ai/__init__.py +30 -0
  3. bear_utils/ai/ai_helpers/__init__.py +130 -0
  4. bear_utils/ai/ai_helpers/_common.py +19 -0
  5. bear_utils/ai/ai_helpers/_config.py +24 -0
  6. bear_utils/ai/ai_helpers/_parsers.py +188 -0
  7. bear_utils/ai/ai_helpers/_types.py +20 -0
  8. bear_utils/cache/__init__.py +119 -0
  9. bear_utils/cli/__init__.py +4 -0
  10. bear_utils/cli/commands.py +59 -0
  11. bear_utils/cli/prompt_helpers.py +166 -0
  12. bear_utils/cli/shell/__init__.py +0 -0
  13. bear_utils/cli/shell/_base_command.py +74 -0
  14. bear_utils/cli/shell/_base_shell.py +390 -0
  15. bear_utils/cli/shell/_common.py +19 -0
  16. bear_utils/config/__init__.py +11 -0
  17. bear_utils/config/config_manager.py +92 -0
  18. bear_utils/config/dir_manager.py +64 -0
  19. bear_utils/config/settings_manager.py +232 -0
  20. bear_utils/constants/__init__.py +16 -0
  21. bear_utils/constants/_exceptions.py +3 -0
  22. bear_utils/constants/_lazy_typing.py +15 -0
  23. bear_utils/constants/date_related.py +36 -0
  24. bear_utils/constants/time_related.py +22 -0
  25. bear_utils/database/__init__.py +6 -0
  26. bear_utils/database/_db_manager.py +104 -0
  27. bear_utils/events/__init__.py +16 -0
  28. bear_utils/events/events_class.py +52 -0
  29. bear_utils/events/events_module.py +65 -0
  30. bear_utils/extras/__init__.py +17 -0
  31. bear_utils/extras/_async_helpers.py +15 -0
  32. bear_utils/extras/_tools.py +178 -0
  33. bear_utils/extras/platform_utils.py +53 -0
  34. bear_utils/extras/wrappers/__init__.py +0 -0
  35. bear_utils/extras/wrappers/add_methods.py +98 -0
  36. bear_utils/files/__init__.py +4 -0
  37. bear_utils/files/file_handlers/__init__.py +3 -0
  38. bear_utils/files/file_handlers/_base_file_handler.py +93 -0
  39. bear_utils/files/file_handlers/file_handler_factory.py +278 -0
  40. bear_utils/files/file_handlers/json_file_handler.py +44 -0
  41. bear_utils/files/file_handlers/log_file_handler.py +33 -0
  42. bear_utils/files/file_handlers/txt_file_handler.py +34 -0
  43. bear_utils/files/file_handlers/yaml_file_handler.py +57 -0
  44. bear_utils/files/ignore_parser.py +298 -0
  45. bear_utils/graphics/__init__.py +4 -0
  46. bear_utils/graphics/bear_gradient.py +140 -0
  47. bear_utils/graphics/image_helpers.py +39 -0
  48. bear_utils/gui/__init__.py +3 -0
  49. bear_utils/gui/gui_tools/__init__.py +5 -0
  50. bear_utils/gui/gui_tools/_settings.py +37 -0
  51. bear_utils/gui/gui_tools/_types.py +12 -0
  52. bear_utils/gui/gui_tools/qt_app.py +145 -0
  53. bear_utils/gui/gui_tools/qt_color_picker.py +119 -0
  54. bear_utils/gui/gui_tools/qt_file_handler.py +138 -0
  55. bear_utils/gui/gui_tools/qt_input_dialog.py +306 -0
  56. bear_utils/logging/__init__.py +25 -0
  57. bear_utils/logging/logger_manager/__init__.py +0 -0
  58. bear_utils/logging/logger_manager/_common.py +47 -0
  59. bear_utils/logging/logger_manager/_console_junk.py +131 -0
  60. bear_utils/logging/logger_manager/_styles.py +91 -0
  61. bear_utils/logging/logger_manager/loggers/__init__.py +0 -0
  62. bear_utils/logging/logger_manager/loggers/_base_logger.py +238 -0
  63. bear_utils/logging/logger_manager/loggers/_base_logger.pyi +50 -0
  64. bear_utils/logging/logger_manager/loggers/_buffer_logger.py +55 -0
  65. bear_utils/logging/logger_manager/loggers/_console_logger.py +249 -0
  66. bear_utils/logging/logger_manager/loggers/_console_logger.pyi +64 -0
  67. bear_utils/logging/logger_manager/loggers/_file_logger.py +141 -0
  68. bear_utils/logging/logger_manager/loggers/_level_sin.py +58 -0
  69. bear_utils/logging/logger_manager/loggers/_logger.py +18 -0
  70. bear_utils/logging/logger_manager/loggers/_sub_logger.py +110 -0
  71. bear_utils/logging/logger_manager/loggers/_sub_logger.pyi +38 -0
  72. bear_utils/logging/loggers.py +76 -0
  73. bear_utils/monitoring/__init__.py +10 -0
  74. bear_utils/monitoring/host_monitor.py +350 -0
  75. bear_utils/time/__init__.py +16 -0
  76. bear_utils/time/_helpers.py +91 -0
  77. bear_utils/time/_time_class.py +316 -0
  78. bear_utils/time/_timer.py +80 -0
  79. bear_utils/time/_tools.py +17 -0
  80. bear_utils/time/time_manager.py +218 -0
  81. bear_utils-0.7.11.dist-info/METADATA +260 -0
  82. bear_utils-0.7.11.dist-info/RECORD +83 -0
  83. bear_utils-0.7.11.dist-info/WHEEL +4 -0
@@ -0,0 +1,119 @@
1
+ from dataclasses import dataclass
2
+
3
+ from PyQt6.QtGui import QColor
4
+ from PyQt6.QtWidgets import QColorDialog
5
+ from rich.color_triplet import ColorTriplet
6
+
7
+ from .qt_app import QTApplication
8
+
9
+
10
+ @dataclass
11
+ class ColorInfo:
12
+ qcolor: QColor
13
+ hex: str
14
+ rgb: ColorTriplet
15
+ rgba: tuple[int, int, int, int]
16
+ hsv: tuple[int, int, int]
17
+
18
+
19
+ class QTColorPicker(QTApplication):
20
+ """Singleton class to manage the color picker dialog."""
21
+
22
+ def select_color(self, initial_color=None, title="Select Color", options=None) -> ColorInfo | None:
23
+ """
24
+ Shows a color selection dialog and returns the selected color.
25
+
26
+ Args:
27
+ initial_color: Initial color to show in the dialog. Can be:
28
+ - QColor object
29
+ - Hex string (e.g., "#FF5733")
30
+ - RGB tuple (e.g., (255, 87, 51))
31
+ title (str): The dialog window title
32
+ options: QColorDialog options (optional)
33
+
34
+ Returns:
35
+ dict: Color information with keys:
36
+ - 'qcolor': QColor object
37
+ - 'hex': Hex string (e.g., "#FF5733")
38
+ - 'rgb': RGB tuple (e.g., (255, 87, 51))
39
+ - 'rgba': RGBA tuple (e.g., (255, 87, 51, 255))
40
+ - 'hsv': HSV tuple (e.g., (16, 80, 100))
41
+ Or None if dialog was canceled
42
+ """
43
+ try:
44
+ dialog = QColorDialog()
45
+
46
+ if title:
47
+ dialog.setWindowTitle(title)
48
+
49
+ if options:
50
+ dialog.setOptions(options)
51
+
52
+ if initial_color:
53
+ if isinstance(initial_color, QColor):
54
+ dialog.setCurrentColor(initial_color)
55
+ elif isinstance(initial_color, str) and initial_color.startswith("#"):
56
+ dialog.setCurrentColor(QColor(initial_color))
57
+ elif isinstance(initial_color, tuple) and len(initial_color) >= 3:
58
+ r, g, b = initial_color[:3]
59
+ a = initial_color[3] if len(initial_color) > 3 else 255
60
+ dialog.setCurrentColor(QColor(r, g, b, a))
61
+
62
+ if dialog.exec() == QColorDialog.DialogCode.Accepted:
63
+ selected_color = dialog.selectedColor()
64
+
65
+ if not selected_color.isValid():
66
+ return None
67
+
68
+ return ColorInfo(
69
+ qcolor=selected_color,
70
+ hex=selected_color.name(),
71
+ rgb=ColorTriplet(selected_color.red(), selected_color.green(), selected_color.blue()),
72
+ rgba=(
73
+ selected_color.red(),
74
+ selected_color.green(),
75
+ selected_color.blue(),
76
+ selected_color.alpha(),
77
+ ),
78
+ hsv=(selected_color.hue(), selected_color.saturation(), selected_color.value()),
79
+ )
80
+ else:
81
+ return None
82
+ except Exception as e:
83
+ self.console.error(f"Error in color selection dialog: {e}")
84
+ return None
85
+
86
+
87
+ def select_color(initial_color=None, title="Select Color", options=None) -> ColorInfo | None:
88
+ """
89
+ Select a color using the QTColorPicker singleton instance.
90
+
91
+ Args:
92
+ initial_color: Initial color to show in the dialog. Can be:
93
+ - QColor object
94
+ - Hex string (e.g., "#FF5733")
95
+ - RGB tuple (e.g., (255, 87, 51))
96
+ title (str): The dialog window title
97
+ options: QColorDialog options (optional)
98
+
99
+ Returns:
100
+ dict: Color information with keys:
101
+ - 'qcolor': QColor object
102
+ - 'hex': Hex string (e.g., "#FF5733")
103
+ - 'rgb': RGB tuple (e.g., (255, 87, 51))
104
+ - 'rgba': RGBA tuple (e.g., (255, 87, 51, 255))
105
+ - 'hsv': HSV tuple (e.g., (16, 80, 100))
106
+ Or None if dialog was canceled
107
+ """
108
+ qt_color_picker = QTColorPicker()
109
+ return qt_color_picker.select_color(initial_color, title, options)
110
+
111
+
112
+ if __name__ == "__main__":
113
+ # Example usage
114
+ color_picker = QTColorPicker()
115
+ selected_color: ColorInfo | None = color_picker.select_color(initial_color="#FF5733", title="Choose a Color")
116
+ if selected_color:
117
+ color_picker.console.info(f"Selected Color: {selected_color}")
118
+ else:
119
+ color_picker.console.warning("No color selected.")
@@ -0,0 +1,138 @@
1
+ from PyQt6.QtWidgets import QFileDialog
2
+
3
+ from .qt_app import QTApplication
4
+
5
+
6
+ class QTFileHandler(QTApplication):
7
+ """A singleton class to handle file selection dialogs using PyQt6."""
8
+
9
+ def select_file(self, caption="Select File", directory="", filter="All Files (*)"):
10
+ """
11
+ Shows a file selection dialog and returns the selected file path.
12
+
13
+ Args:
14
+ caption (str): The dialog window title
15
+ directory (str): The starting directory
16
+ filter (str): File filter pattern (e.g., "Images (*.png *.jpg);;Text files (*.txt)")
17
+
18
+ Returns:
19
+ str: Selected file path or empty string if canceled
20
+ """
21
+ file_path, _ = QFileDialog.getOpenFileName(None, caption, directory, filter)
22
+ return file_path
23
+
24
+ def select_files(self, caption="Select Files", directory="", filter="All Files (*)"):
25
+ """
26
+ Shows a file selection dialog that allows multiple selections.
27
+
28
+ Returns:
29
+ list: List of selected file paths
30
+ """
31
+ file_paths, _ = QFileDialog.getOpenFileNames(None, caption, directory, filter)
32
+ return file_paths
33
+
34
+ def select_directory(self, caption="Select Directory", directory=""):
35
+ """
36
+ Shows a directory selection dialog.
37
+
38
+ Returns:
39
+ str: Selected directory path or empty string if canceled
40
+ """
41
+ dir_path = QFileDialog.getExistingDirectory(None, caption, directory)
42
+ return dir_path
43
+
44
+ def save_file_dialog(self, caption="Save File", directory="", filter="All Files (*)"):
45
+ """
46
+ Shows a save file dialog.
47
+
48
+ Returns:
49
+ str: Selected save file path or empty string if canceled
50
+ """
51
+
52
+ file_path, _ = QFileDialog.getSaveFileName(None, caption, directory, filter)
53
+ return file_path
54
+
55
+
56
+ def select_file(caption="Select File", directory="", filter="All Files (*)"):
57
+ """
58
+ Select a file using the QTApplication singleton instance.
59
+
60
+ Args:
61
+ caption (str): The dialog window title
62
+ directory (str): The starting directory
63
+ filter (str): File filter pattern (e.g., "Images (*.png *.jpg);;Text files (*.txt)")
64
+
65
+ Returns:
66
+ str: Selected file path or empty string if canceled
67
+ """
68
+ qt_app = QTFileHandler()
69
+ return qt_app.select_file(caption, directory, filter)
70
+
71
+
72
+ def select_files(caption="Select Files", directory="", filter="All Files (*)"):
73
+ """
74
+ Select multiple files using the QTApplication singleton instance.
75
+
76
+ Args:
77
+ caption (str): The dialog window title
78
+ directory (str): The starting directory
79
+ filter (str): File filter pattern (e.g., "Images (*.png *.jpg);;Text files (*.txt)")
80
+
81
+ Returns:
82
+ list: List of selected file paths
83
+ """
84
+ qt_app = QTFileHandler()
85
+ return qt_app.select_files(caption, directory, filter)
86
+
87
+
88
+ def select_directory(caption="Select Directory", directory=""):
89
+ """
90
+ Select a directory using the QTApplication singleton instance.
91
+
92
+ Args:
93
+ caption (str): The dialog window title
94
+ directory (str): The starting directory
95
+
96
+ Returns:
97
+ str: Selected directory path or empty string if canceled
98
+ """
99
+ qt_app = QTFileHandler()
100
+ return qt_app.select_directory(caption, directory)
101
+
102
+
103
+ def save_file_dialog(caption="Save File", directory="", filter="All Files (*)"):
104
+ """
105
+ Show a save file dialog using the QTApplication singleton instance.
106
+
107
+ Args:
108
+ caption (str): The dialog window title
109
+ directory (str): The starting directory
110
+ filter (str): File filter pattern (e.g., "Images (*.png *.jpg);;Text files (*.txt)")
111
+
112
+ Returns:
113
+ str: Selected save file path or empty string if canceled
114
+ """
115
+ qt_app = QTFileHandler()
116
+ return qt_app.save_file_dialog(caption, directory, filter)
117
+
118
+
119
+ __all__ = [
120
+ "QTFileHandler",
121
+ "select_file",
122
+ "select_files",
123
+ "select_directory",
124
+ "save_file_dialog",
125
+ ]
126
+
127
+
128
+ # if __name__ == "__main__":
129
+ # # Example usage
130
+ # selected_file = select_file(
131
+ # "Select a file", filter="Python files (*.py);;All files (*)"
132
+ # )
133
+ # print(f"Selected file: {selected_file}")
134
+
135
+ # selected_files = select_files(
136
+ # "Select multiple files", filter="Images (*.png *.jpg);;All files (*)"
137
+ # )
138
+ # print(f"Selected files: {selected_files}")
@@ -0,0 +1,306 @@
1
+ from PyQt6.QtCore import Qt
2
+ from PyQt6.QtWidgets import QInputDialog, QLineEdit
3
+
4
+ from .qt_app import QTApplication
5
+
6
+
7
+ class InputDialog(QTApplication):
8
+ def get_text(
9
+ self,
10
+ title: str = "Input",
11
+ label: str = "Enter text:",
12
+ default: str = "",
13
+ echo_mode: QLineEdit.EchoMode = QLineEdit.EchoMode.Normal,
14
+ ) -> str | None:
15
+ """
16
+ Shows a text input dialog.
17
+
18
+ Args:
19
+ title: Dialog window title
20
+ label: Text label above the input field
21
+ default: Default text in the input field
22
+ echo_mode: How text is displayed (Normal, Password, etc.)
23
+ input_mode: Type of text input (TextInput, IntInput, etc.)
24
+
25
+ Returns:
26
+ str: Entered text or None if canceled
27
+ """
28
+ try:
29
+ text, ok = QInputDialog.getText(
30
+ None,
31
+ title,
32
+ label,
33
+ echo_mode,
34
+ default,
35
+ Qt.WindowType.Dialog | Qt.WindowType.WindowCloseButtonHint,
36
+ )
37
+ return text if ok else None
38
+ except Exception as e:
39
+ self.console.error(f"Error in text input dialog: {e}")
40
+ return None
41
+
42
+ def get_password(
43
+ self,
44
+ title: str = "Password",
45
+ label: str = "Enter password:",
46
+ default: str = "",
47
+ ) -> str | None:
48
+ """
49
+ Shows a password input dialog with masked text.
50
+
51
+ Args:
52
+ title: Dialog window title
53
+ label: Text label above the input field
54
+ default: Default text in the input field
55
+
56
+ Returns:
57
+ str: Entered password or None if canceled
58
+ """
59
+ return self.get_text(
60
+ title=title,
61
+ label=label,
62
+ default=default,
63
+ echo_mode=QLineEdit.EchoMode.Password,
64
+ )
65
+
66
+ def get_int(
67
+ self,
68
+ title: str = "Input",
69
+ label: str = "Enter number:",
70
+ default: int = 0,
71
+ min_value: int = -2147483647,
72
+ max_value: int = 2147483647,
73
+ step: int = 1,
74
+ ) -> int | None:
75
+ """
76
+ Shows an integer input dialog with spinner.
77
+
78
+ Args:
79
+ title: Dialog window title
80
+ label: Text label above the input field
81
+ default: Default value
82
+ min_value: Minimum allowed value
83
+ max_value: Maximum allowed value
84
+ step: Step size for spinner buttons
85
+
86
+ Returns:
87
+ int: Entered integer or None if canceled
88
+ """
89
+ try:
90
+ value, ok = QInputDialog.getInt(
91
+ None,
92
+ title,
93
+ label,
94
+ default,
95
+ min_value,
96
+ max_value,
97
+ step,
98
+ Qt.WindowType.Dialog | Qt.WindowType.WindowCloseButtonHint,
99
+ )
100
+ return value if ok else None
101
+ except Exception as e:
102
+ self.console.error(f"Error in integer input dialog: {e}")
103
+ return None
104
+
105
+ def get_double(
106
+ self,
107
+ title: str = "Input",
108
+ label: str = "Enter number:",
109
+ default: float = 0.0,
110
+ min_value: float = -2147483647.0,
111
+ max_value: float = 2147483647.0,
112
+ decimals: int = 2,
113
+ ) -> float | None:
114
+ """
115
+ Shows a floating-point input dialog with spinner.
116
+
117
+ Args:
118
+ title: Dialog window title
119
+ label: Text label above the input field
120
+ default: Default value
121
+ min_value: Minimum allowed value
122
+ max_value: Maximum allowed value
123
+ decimals: Number of decimal places to show
124
+
125
+ Returns:
126
+ float: Entered value or None if canceled
127
+ """
128
+ try:
129
+ value, ok = QInputDialog.getDouble(
130
+ None,
131
+ title,
132
+ label,
133
+ default,
134
+ min_value,
135
+ max_value,
136
+ decimals,
137
+ Qt.WindowType.Dialog | Qt.WindowType.WindowCloseButtonHint,
138
+ )
139
+ return value if ok else None
140
+ except Exception as e:
141
+ self.console.error(f"Error in double input dialog: {e}")
142
+ return None
143
+
144
+ def get_item(
145
+ self,
146
+ title: str = "Select",
147
+ label: str = "Select an item:",
148
+ items: list[str] | None = None,
149
+ current: int = 0,
150
+ editable: bool = False,
151
+ ) -> str | None:
152
+ """
153
+ Shows a dropdown selection dialog.
154
+
155
+ Args:
156
+ title: Dialog window title
157
+ label: Text label above the dropdown
158
+ items: List of items to choose from
159
+ current: Index of the initially selected item
160
+ editable: Whether the text can be edited
161
+
162
+ Returns:
163
+ str: Selected or entered text, or None if canceled
164
+ """
165
+ if items is None:
166
+ items = ["Item 1", "Item 2", "Item 3"]
167
+
168
+ try:
169
+ item, ok = QInputDialog.getItem(
170
+ None,
171
+ title,
172
+ label,
173
+ items,
174
+ current,
175
+ editable,
176
+ Qt.WindowType.Dialog | Qt.WindowType.WindowCloseButtonHint,
177
+ )
178
+ return item if ok else None
179
+ except Exception as e:
180
+ self.console.error(f"Error in item selection dialog: {e}")
181
+ return None
182
+
183
+ def get_multiline_text(self, title: str = "Input", label: str = "Enter text:", default: str = "") -> str | None:
184
+ """
185
+ Shows a multi-line text input dialog.
186
+
187
+ Args:
188
+ title: Dialog window title
189
+ label: Text label above the input field
190
+ default: Default text in the input field
191
+
192
+ Returns:
193
+ str: Entered text or None if canceled
194
+ """
195
+ try:
196
+ text, ok = QInputDialog.getMultiLineText(
197
+ None,
198
+ title,
199
+ label,
200
+ default,
201
+ Qt.WindowType.Dialog | Qt.WindowType.WindowCloseButtonHint,
202
+ )
203
+ return text if ok else None
204
+ except Exception as e:
205
+ self.console.error(f"Error in multiline text input dialog: {e}")
206
+ return None
207
+
208
+
209
+ def get_text(
210
+ title: str = "Input",
211
+ label: str = "Enter text:",
212
+ default: str = "",
213
+ echo_mode: QLineEdit.EchoMode = QLineEdit.EchoMode.Normal,
214
+ ) -> str | None:
215
+ """Displays a text input dialog and returns the text entered by the user."""
216
+ qt_app = InputDialog()
217
+ return qt_app.get_text(title, label, default, echo_mode)
218
+
219
+
220
+ def get_password(title: str = "Password", label: str = "Enter password:", default: str = "") -> str | None:
221
+ """Displays a password input dialog with masked text."""
222
+ qt_app = InputDialog()
223
+ return qt_app.get_password(title, label, default)
224
+
225
+
226
+ def get_api_key(
227
+ title: str = "API Key Required",
228
+ label: str = "Enter API key:",
229
+ default: str = "",
230
+ service_name: str = "",
231
+ ) -> str | None:
232
+ """
233
+ Shows a secure input dialog optimized for entering API keys.
234
+
235
+ Args:
236
+ title: Dialog window title
237
+ label: Text label above the input field
238
+ default: Default API key (rarely used, but available)
239
+ service_name: Name of the service requiring the API key
240
+
241
+ Returns:
242
+ str: Entered API key or None if canceled
243
+ """
244
+ qt_app = InputDialog()
245
+
246
+ # Customize the label if service name is provided
247
+ if service_name:
248
+ label = f"Enter API key for {service_name}:"
249
+ title = f"{service_name} API Key"
250
+
251
+ return qt_app.get_text(title=title, label=label, default=default, echo_mode=QLineEdit.EchoMode.Password)
252
+
253
+
254
+ def get_int(
255
+ title: str = "Input",
256
+ label: str = "Enter number:",
257
+ default: int = 0,
258
+ min_value: int = -2147483647,
259
+ max_value: int = 2147483647,
260
+ step: int = 1,
261
+ ) -> int | None:
262
+ """Displays an integer input dialog with spinner buttons."""
263
+ qt_app = InputDialog()
264
+ return qt_app.get_int(title, label, default, min_value, max_value, step)
265
+
266
+
267
+ def get_double(
268
+ title: str = "Input",
269
+ label: str = "Enter number:",
270
+ default: float = 0.0,
271
+ min_value: float = -2147483647.0,
272
+ max_value: float = 2147483647.0,
273
+ decimals: int = 2,
274
+ ) -> float | None:
275
+ """Displays a floating-point input dialog with spinner buttons."""
276
+ qt_app = InputDialog()
277
+ return qt_app.get_double(title, label, default, min_value, max_value, decimals)
278
+
279
+
280
+ def get_item(
281
+ title: str = "Select",
282
+ label: str = "Select an item:",
283
+ items: list[str] | None = None,
284
+ current: int = 0,
285
+ editable: bool = False,
286
+ ) -> str | None:
287
+ """Displays a dropdown selection dialog."""
288
+ qt_app = InputDialog()
289
+ return qt_app.get_item(title, label, items, current, editable)
290
+
291
+
292
+ def get_multiline_text(title: str = "Input", label: str = "Enter text:", default: str = "") -> str | None:
293
+ """Displays a multi-line text input dialog."""
294
+ qt_app = InputDialog()
295
+ return qt_app.get_multiline_text(title, label, default)
296
+
297
+
298
+ if __name__ == "__main__":
299
+ # Example usage
300
+ api_key = get_api_key(
301
+ title="API Key Required",
302
+ label="Enter your API key:",
303
+ default="",
304
+ service_name="MyService",
305
+ )
306
+ print(f"API Key: {api_key}")
@@ -0,0 +1,25 @@
1
+ from .logger_manager._common import VERBOSE_CONSOLE_FORMAT
2
+ from .logger_manager._styles import VERBOSE
3
+ from .loggers import (
4
+ BaseLogger,
5
+ BufferLogger,
6
+ ConsoleLogger,
7
+ FileLogger,
8
+ SubConsoleLogger,
9
+ get_console,
10
+ get_logger,
11
+ get_sub_logger,
12
+ )
13
+
14
+ __all__ = [
15
+ "BaseLogger",
16
+ "ConsoleLogger",
17
+ "BufferLogger",
18
+ "SubConsoleLogger",
19
+ "FileLogger",
20
+ "get_console",
21
+ "get_logger",
22
+ "get_sub_logger",
23
+ "VERBOSE",
24
+ "VERBOSE_CONSOLE_FORMAT",
25
+ ]
File without changes
@@ -0,0 +1,47 @@
1
+ import inspect
2
+ from types import TracebackType
3
+ from typing import Required, TypedDict
4
+
5
+
6
+ class ExecValues(TypedDict, total=True):
7
+
8
+ exc_type: Required[type[BaseException]]
9
+ exc_value: Required[BaseException]
10
+ exc_traceback: Required[TracebackType]
11
+
12
+
13
+ VERBOSE_FORMAT = "%(asctime)s |%(levelname)s| {%(module)s|%(funcName)s|%(lineno)d} %(message)s"
14
+ VERBOSE_CONSOLE_FORMAT = "%(asctime)s <[{}]{}[/{}]> %(message)s"
15
+ SIMPLE_FORMAT = "%(message)s"
16
+ FIVE_MEGABYTES = 1024 * 1024 * 5
17
+
18
+
19
+ class StackLevelTracker:
20
+ STACK_LEVEL_OFFSET = 1
21
+
22
+ def __init__(self) -> None:
23
+ self.start_depth: int | None = None
24
+ self.end_depth: int | None = None
25
+
26
+ @property
27
+ def not_set(self) -> bool:
28
+ """Check if the start depth is not set."""
29
+ return self.start_depth is None
30
+
31
+ def record_start(self) -> None:
32
+ """Record the current stack depth as the start depth."""
33
+ self.start_depth = len(inspect.stack())
34
+
35
+ def record_end(self) -> int:
36
+ """Record the current stack depth as the end depth and then return the calculated stack level.
37
+
38
+ Returns:
39
+ int: The calculated stack level based on the difference between start and end depths.
40
+ """
41
+ self.end_depth = len(inspect.stack())
42
+ return self.calculate_stacklevel()
43
+
44
+ def calculate_stacklevel(self) -> int:
45
+ if self.start_depth is None or self.end_depth is None:
46
+ raise ValueError("Start and end depths must be recorded before calculating stack level.")
47
+ return self.end_depth - (self.start_depth + self.STACK_LEVEL_OFFSET)