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,278 @@
1
+ import warnings
2
+ from pathlib import Path
3
+ from typing import Any, cast
4
+
5
+ from ._base_file_handler import FileHandler
6
+
7
+
8
+ class FileHandlerFactory:
9
+ """Factory class to create and manage FileHandler instances based on file types.
10
+
11
+ This factory maintains state about the current file path and can create appropriate
12
+ handlers for different file types.
13
+ """
14
+
15
+ def __init__(self, file_path: Path | None = None) -> None:
16
+ """Initialize the factory with an optional file path.
17
+
18
+ Args:
19
+ file_path: Optional Path to the file to handle
20
+ """
21
+ self._file_path: Path | None = file_path
22
+ self._handler_registry: dict[str, type[FileHandler]] = {}
23
+ self._handler_instance: FileHandler | None = None
24
+ self._register_default_handlers()
25
+
26
+ @property
27
+ def file_path(self) -> Path | None:
28
+ """Get the current file path."""
29
+ return self._file_path
30
+
31
+ @file_path.setter
32
+ def file_path(self, path: Path) -> None:
33
+ """Set the current file path and reset the handler instance.
34
+
35
+ Args:
36
+ path: New file path to set
37
+ """
38
+ self._file_path = path
39
+ self._handler_instance = None
40
+
41
+ def _register_default_handlers(self) -> None:
42
+ """Register all default handlers from the package.
43
+
44
+ This method imports and registers all standard FileHandler implementations.
45
+ """
46
+ try:
47
+ from .json_file_handler import JsonFileHandler
48
+ from .log_file_handler import LogFileHandler
49
+ from .txt_file_handler import TextFileHandler
50
+ from .yaml_file_handler import YamlFileHandler
51
+
52
+ self.register_handler(JsonFileHandler)
53
+ self.register_handler(TextFileHandler)
54
+ self.register_handler(YamlFileHandler)
55
+ self.register_handler(LogFileHandler)
56
+
57
+ except ImportError as e:
58
+ warnings.warn(f"Could not import all default handlers: {e}")
59
+
60
+ def register_handler(self, handler_class: type[FileHandler]) -> None:
61
+ """Register a handler class for its supported extensions.
62
+
63
+ Args:
64
+ handler_class: The FileHandler class to register
65
+ """
66
+ for ext in handler_class.valid_extensions:
67
+ self._handler_registry[ext] = handler_class
68
+
69
+ def get_handler_class(self, extension: str) -> type[FileHandler] | None:
70
+ """Get the handler class for a specific extension.
71
+
72
+ Args:
73
+ extension: File extension (without the dot)
74
+
75
+ Returns:
76
+ FileHandler class for the extension or None if not found
77
+ """
78
+ return self._handler_registry.get(extension)
79
+
80
+ def get_handler_for_path(self, file_path: Path | None = None) -> FileHandler:
81
+ """Get or create a handler instance for the given path or the current path.
82
+
83
+ Args:
84
+ file_path: Path to get handler for (uses stored path if None)
85
+
86
+ Returns:
87
+ Appropriate FileHandler instance
88
+
89
+ Raises:
90
+ ValueError: If no file path is provided or stored, or if no handler exists for the file extension
91
+ """
92
+ path = file_path or self._file_path
93
+ if not path:
94
+ raise ValueError("No file path provided or stored in factory")
95
+
96
+ if file_path:
97
+ self._file_path = file_path
98
+ self._handler_instance = None
99
+
100
+ if self._handler_instance and not file_path:
101
+ return self._handler_instance
102
+
103
+ extension = path.suffix.lstrip(".")
104
+ handler_class = self.get_handler_class(extension)
105
+
106
+ if not handler_class:
107
+ raise ValueError(f"No handler registered for extension: {extension}")
108
+
109
+ handler = handler_class()
110
+ if not file_path: # Only cache if using the stored path
111
+ self._handler_instance = handler
112
+
113
+ return handler
114
+
115
+ def handle_file(self, operation: str, file_path: Path | None = None, data: Any = None, **kwargs) -> Any:
116
+ """Handle file operations using the appropriate handler.
117
+
118
+ Args:
119
+ operation: Operation to perform ('read', 'write', 'present', 'info')
120
+ file_path: Path to the file (uses stored path if None)
121
+ data: Data for write operations
122
+ **kwargs: Additional arguments for the operation
123
+
124
+ Returns:
125
+ Result of the operation
126
+
127
+ Raises:
128
+ ValueError: If an invalid operation is specified
129
+ """
130
+ path: Path | None = file_path or self._file_path
131
+ if not path and operation != "present":
132
+ raise ValueError("File path required for this operation")
133
+
134
+ match operation:
135
+ case "read":
136
+ handler = self.get_handler_for_path(path)
137
+ return handler.read_file(cast(Path, path), **kwargs)
138
+ case "write":
139
+ if data is None:
140
+ raise ValueError("Data required for write operation")
141
+ handler = self.get_handler_for_path(path)
142
+ return handler.write_file(cast(Path, path), data, **kwargs)
143
+ case "present":
144
+ if data is None:
145
+ raise ValueError("Data required for present operation")
146
+ if path:
147
+ handler: FileHandler = self.get_handler_for_path(path)
148
+ else:
149
+ if isinstance(data, dict):
150
+ yaml_class = self.get_handler_class("yaml")
151
+ if yaml_class:
152
+ handler = yaml_class()
153
+ else:
154
+ raise ValueError("No handler available for dict data")
155
+ elif isinstance(data, str):
156
+ text_class = self.get_handler_class("txt")
157
+ if text_class:
158
+ handler = text_class()
159
+ else:
160
+ raise ValueError("No handler available for string data")
161
+ else:
162
+ raise ValueError(f"Cannot determine handler for data type: {type(data)}")
163
+ return handler.present_file(data)
164
+
165
+ case "info":
166
+ handler = self.get_handler_for_path(path)
167
+ return handler.get_file_info(cast(Path, path))
168
+ case _:
169
+ raise ValueError(f"Invalid operation: {operation}")
170
+
171
+ def read(self, file_path: Path | None = None, **kwargs) -> Any:
172
+ """Read a file using the appropriate handler.
173
+
174
+ Args:
175
+ file_path: Path to read (uses stored path if None)
176
+ **kwargs: Additional arguments for read_file
177
+
178
+ Returns:
179
+ File contents
180
+ """
181
+ return self.handle_file("read", file_path, **kwargs)
182
+
183
+ def write(self, data: dict | str, file_path: Path | None = None, **kwargs) -> None:
184
+ """Write to a file using the appropriate handler.
185
+
186
+ Args:
187
+ data: Data to write
188
+ file_path: Path to write to (uses stored path if None)
189
+ **kwargs: Additional arguments for write_file
190
+ """
191
+ return self.handle_file("write", file_path, data, **kwargs)
192
+
193
+ def present(self, data: dict | str, file_path: Path | None = None) -> str:
194
+ """Present data using the appropriate handler.
195
+
196
+ Args:
197
+ data: Data to present
198
+ file_path: Optional path to determine format (uses stored path if None)
199
+
200
+ Returns:
201
+ String representation of the data
202
+ """
203
+ return self.handle_file("present", file_path, data)
204
+
205
+ def get_info(self, file_path: Path | None = None) -> dict[str, Any]:
206
+ """Get information about a file.
207
+
208
+ Args:
209
+ file_path: Path to get info for (uses stored path if None)
210
+
211
+ Returns:
212
+ Dictionary with file information
213
+ """
214
+ return self.handle_file("info", file_path)
215
+
216
+ def convert(self, source_path: Path, target_path: Path, **kwargs) -> None:
217
+ """Convert a file from one format to another.
218
+
219
+ Args:
220
+ source_path: Path to the source file
221
+ target_path: Path to the target file
222
+ **kwargs: Additional arguments for read_file and write_file
223
+ """
224
+ source_handler = self.get_handler_for_path(source_path)
225
+ data = source_handler.read_file(source_path, **kwargs)
226
+
227
+ target_handler = self.get_handler_for_path(target_path)
228
+ target_handler.write_file(target_path, data, **kwargs)
229
+
230
+
231
+ _default_factory = FileHandlerFactory()
232
+
233
+
234
+ def get_handler_for_file(file_path: Path) -> FileHandler:
235
+ """Get a handler for the given file path.
236
+
237
+ Args:
238
+ file_path: Path to the file
239
+
240
+ Returns:
241
+ Appropriate FileHandler instance
242
+ """
243
+ return _default_factory.get_handler_for_path(file_path)
244
+
245
+
246
+ def read_file(file_path: Path, **kwargs) -> Any:
247
+ """Read a file using the appropriate handler.
248
+
249
+ Args:
250
+ file_path: Path to the file
251
+ **kwargs: Additional arguments for read_file
252
+
253
+ Returns:
254
+ File contents
255
+ """
256
+ return _default_factory.read(file_path, **kwargs)
257
+
258
+
259
+ def write_file(file_path: Path, data: Any, **kwargs) -> None:
260
+ """Write to a file using the appropriate handler.
261
+
262
+ Args:
263
+ file_path: Path to the file
264
+ data: Data to write
265
+ **kwargs: Additional arguments for write_file
266
+ """
267
+ return _default_factory.write(data, file_path, **kwargs)
268
+
269
+
270
+ def convert_file(source_path: Path, target_path: Path, **kwargs) -> None:
271
+ """Convert a file from one format to another.
272
+
273
+ Args:
274
+ source_path: Path to the source file
275
+ target_path: Path to the target file
276
+ **kwargs: Additional arguments for read_file and write_file
277
+ """
278
+ return _default_factory.convert(source_path, target_path, **kwargs)
@@ -0,0 +1,44 @@
1
+ import json
2
+ from pathlib import Path
3
+ from typing import Any, ClassVar
4
+
5
+ from ._base_file_handler import FileHandler
6
+
7
+
8
+ class JsonFileHandler(FileHandler):
9
+ """Class for handling JSON files with read, write, and present methods"""
10
+
11
+ valid_extensions: ClassVar[list[str]] = ["json"]
12
+
13
+ @FileHandler.ValidateFileType
14
+ def read_file(self, file_path: Path, **kwargs) -> dict[str, Any]:
15
+ try:
16
+ super().read_file(file_path)
17
+ with open(file_path, "r", encoding="utf-8") as file:
18
+ return json.load(file, **kwargs)
19
+ except Exception as e:
20
+ raise ValueError(f"Error reading file: {e}")
21
+
22
+ @FileHandler.ValidateFileType
23
+ def write_file(self, file_path: Path, data: dict[str, Any] | str, **kwargs) -> None:
24
+ try:
25
+ super().write_file(file_path, data)
26
+ with open(file_path, "w", encoding="utf-8") as file:
27
+ json.dump(
28
+ data,
29
+ file,
30
+ indent=kwargs.pop("indent", 4),
31
+ **kwargs,
32
+ )
33
+ except Exception as e:
34
+ raise ValueError(f"Error writing file: {e}")
35
+
36
+ def present_file(self, data: dict[str, Any] | str, **kwargs) -> str:
37
+ try:
38
+ return json.dumps(
39
+ data,
40
+ indent=kwargs.pop("indent", 4),
41
+ **kwargs,
42
+ )
43
+ except Exception as e:
44
+ raise ValueError(f"Error presenting file: {e}")
@@ -0,0 +1,33 @@
1
+ from pathlib import Path
2
+ from typing import Any, ClassVar
3
+
4
+ from ._base_file_handler import FileHandler
5
+
6
+
7
+ class LogFileHandler(FileHandler):
8
+ """Class for handling .log files with read, write, and present methods"""
9
+
10
+ valid_extensions: ClassVar[list[str]] = ["log"]
11
+
12
+ @FileHandler.ValidateFileType
13
+ def read_file(self, file_path: Path) -> str:
14
+ try:
15
+ super().read_file(file_path)
16
+ with open(file_path, "r", encoding="utf-8") as file:
17
+ return file.read()
18
+ except Exception as e:
19
+ raise ValueError(f"Error reading file: {e}")
20
+
21
+ @FileHandler.ValidateFileType
22
+ def write_file(self, file_path: Path, data: dict[str, Any] | str, **kwargs) -> None:
23
+ try:
24
+ super().write_file(file_path, data)
25
+ if not isinstance(data, str):
26
+ raise ValueError("Data must be a string for log files")
27
+ with open(file_path, "w", encoding="utf-8") as file:
28
+ file.write(data)
29
+ except Exception as e:
30
+ raise ValueError(f"Error writing file: {e}")
31
+
32
+ def present_file(self, data: dict[str, Any] | str, **kwargs) -> str:
33
+ raise NotImplementedError("Presenting log files is not implemented. Not needed.")
@@ -0,0 +1,34 @@
1
+ from pathlib import Path
2
+ from typing import Any, ClassVar
3
+
4
+ from ._base_file_handler import FileHandler
5
+
6
+
7
+ class TextFileHandler(FileHandler):
8
+ """Class for handling .txt files with read, write, and present methods"""
9
+
10
+ valid_extensions: ClassVar[list[str]] = ["txt"]
11
+
12
+ @FileHandler.ValidateFileType
13
+ def read_file(self, file_path: Path) -> str:
14
+ try:
15
+ super().read_file(file_path)
16
+ with open(file_path, "r", encoding="utf-8") as file:
17
+ return file.read()
18
+ except Exception as e:
19
+ raise ValueError(f"Error reading file: {e}")
20
+
21
+ @FileHandler.ValidateFileType
22
+ def write_file(self, file_path: Path, data: dict[str, Any] | str, **kwargs) -> None:
23
+ try:
24
+ super().write_file(file_path, data)
25
+ if not isinstance(data, str):
26
+ raise ValueError("Data must be a string for text files")
27
+
28
+ with open(file_path, "w", encoding="utf-8") as file:
29
+ file.write(data)
30
+ except Exception as e:
31
+ raise ValueError(f"Error writing file: {e}")
32
+
33
+ def present_file(self, data: dict[str, Any] | str, **kwargs) -> str:
34
+ raise NotImplementedError("Presenting text files is not implemented. Not needed.")
@@ -0,0 +1,57 @@
1
+ from pathlib import Path
2
+ from typing import Any, ClassVar
3
+
4
+ import yaml
5
+
6
+ from ._base_file_handler import FileHandler
7
+
8
+
9
+ class YamlFileHandler(FileHandler):
10
+ """Class for handling .yaml/.yml files with read, write, and present methods"""
11
+
12
+ valid_extensions: ClassVar[list[str]] = ["yaml", "yml"]
13
+
14
+ @FileHandler.ValidateFileType
15
+ def unsafe_read_file(self, file_path: Path, **kwargs) -> dict[str, Any]:
16
+ """Read YAML file with potentially unsafe loader.
17
+
18
+ WARNING: This method can execute arbitrary code and should only be used
19
+ with trusted files.
20
+
21
+ Args:
22
+ file_path: Path to the YAML file
23
+ **kwargs: Additional arguments passed to yaml.load
24
+
25
+ Returns:
26
+ Dictionary containing the parsed YAML data
27
+ """
28
+ try:
29
+ super().read_file(file_path)
30
+ with open(file_path, "r", encoding="utf-8") as file:
31
+ return yaml.load(file, **kwargs)
32
+ except Exception as e:
33
+ raise ValueError(f"Error reading file: {e}")
34
+
35
+ @FileHandler.ValidateFileType
36
+ def read_file(self, file_path: Path) -> dict[str, Any]:
37
+ try:
38
+ super().read_file(file_path)
39
+ with open(file_path, "r", encoding="utf-8") as file:
40
+ return yaml.safe_load(file)
41
+ except Exception as e:
42
+ raise ValueError(f"Error reading file: {e}")
43
+
44
+ @FileHandler.ValidateFileType
45
+ def write_file(self, file_path: Path, data: dict[str, Any] | str, **kwargs) -> None:
46
+ try:
47
+ super().write_file(file_path, data)
48
+ with open(file_path, "w", encoding="utf-8") as file:
49
+ yaml.dump(data, file, default_flow_style=False, sort_keys=False, **kwargs)
50
+ except Exception as e:
51
+ raise ValueError(f"Error writing file: {e}")
52
+
53
+ def present_file(self, data: dict[str, Any] | str, **kwargs) -> str:
54
+ try:
55
+ return yaml.dump(data, default_flow_style=False, sort_keys=False, **kwargs)
56
+ except Exception as e:
57
+ raise ValueError(f"Error presenting file: {e}")