bear-utils 0.7.19__tar.gz → 0.7.21__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.
Files changed (95) hide show
  1. {bear_utils-0.7.19 → bear_utils-0.7.21}/.bumpversion.cfg +1 -1
  2. {bear_utils-0.7.19 → bear_utils-0.7.21}/PKG-INFO +2 -3
  3. {bear_utils-0.7.19 → bear_utils-0.7.21}/README.md +1 -1
  4. {bear_utils-0.7.19 → bear_utils-0.7.21}/pyproject.toml +4 -2
  5. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/cli/shell/_base_shell.py +75 -25
  6. bear_utils-0.7.21/src/bear_utils/gui/__init__.py +6 -0
  7. bear_utils-0.7.21/src/bear_utils/gui/gui_tools/__init__.py +8 -0
  8. bear_utils-0.7.19/src/bear_utils/gui/__init__.py +0 -3
  9. bear_utils-0.7.19/src/bear_utils/gui/gui_tools/__init__.py +0 -5
  10. {bear_utils-0.7.19 → bear_utils-0.7.21}/.gitignore +0 -0
  11. {bear_utils-0.7.19 → bear_utils-0.7.21}/.python-version +0 -0
  12. {bear_utils-0.7.19 → bear_utils-0.7.21}/AGENTS.md +0 -0
  13. {bear_utils-0.7.19 → bear_utils-0.7.21}/directory_structure.txt +0 -0
  14. {bear_utils-0.7.19 → bear_utils-0.7.21}/maskfile.md +0 -0
  15. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/__init__.py +0 -0
  16. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/ai/__init__.py +0 -0
  17. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/ai/ai_helpers/__init__.py +0 -0
  18. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/ai/ai_helpers/_common.py +0 -0
  19. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/ai/ai_helpers/_config.py +0 -0
  20. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/ai/ai_helpers/_parsers.py +0 -0
  21. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/ai/ai_helpers/_types.py +0 -0
  22. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/cache/__init__.py +0 -0
  23. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/cli/__init__.py +0 -0
  24. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/cli/commands.py +0 -0
  25. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/cli/prompt_helpers.py +0 -0
  26. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/cli/shell/__init__.py +0 -0
  27. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/cli/shell/_base_command.py +0 -0
  28. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/cli/shell/_common.py +0 -0
  29. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/config/__init__.py +0 -0
  30. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/config/config_manager.py +0 -0
  31. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/config/dir_manager.py +0 -0
  32. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/config/settings_manager.py +0 -0
  33. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/constants/__init__.py +0 -0
  34. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/constants/_exceptions.py +0 -0
  35. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/constants/_lazy_typing.py +0 -0
  36. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/constants/date_related.py +0 -0
  37. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/constants/time_related.py +0 -0
  38. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/database/__init__.py +0 -0
  39. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/database/_db_manager.py +0 -0
  40. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/events/__init__.py +0 -0
  41. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/events/events_class.py +0 -0
  42. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/events/events_module.py +0 -0
  43. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/extras/__init__.py +0 -0
  44. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/extras/_async_helpers.py +0 -0
  45. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/extras/_tools.py +0 -0
  46. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/extras/platform_utils.py +0 -0
  47. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/extras/wrappers/__init__.py +0 -0
  48. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/extras/wrappers/add_methods.py +0 -0
  49. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/files/__init__.py +0 -0
  50. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/files/file_handlers/__init__.py +0 -0
  51. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/files/file_handlers/_base_file_handler.py +0 -0
  52. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/files/file_handlers/file_handler_factory.py +0 -0
  53. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/files/file_handlers/json_file_handler.py +0 -0
  54. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/files/file_handlers/log_file_handler.py +0 -0
  55. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/files/file_handlers/toml_file_handler.py +0 -0
  56. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/files/file_handlers/txt_file_handler.py +0 -0
  57. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/files/file_handlers/yaml_file_handler.py +0 -0
  58. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/files/ignore_parser.py +0 -0
  59. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/graphics/__init__.py +0 -0
  60. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/graphics/bear_gradient.py +0 -0
  61. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/graphics/image_helpers.py +0 -0
  62. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/gui/gui_tools/_settings.py +0 -0
  63. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/gui/gui_tools/_types.py +0 -0
  64. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/gui/gui_tools/qt_app.py +0 -0
  65. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/gui/gui_tools/qt_color_picker.py +0 -0
  66. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/gui/gui_tools/qt_file_handler.py +0 -0
  67. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/gui/gui_tools/qt_input_dialog.py +0 -0
  68. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/__init__.py +0 -0
  69. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/__init__.py +0 -0
  70. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/_common.py +0 -0
  71. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/_console_junk.py +0 -0
  72. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/_styles.py +0 -0
  73. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/loggers/__init__.py +0 -0
  74. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/loggers/_base_logger.py +0 -0
  75. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/loggers/_base_logger.pyi +0 -0
  76. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/loggers/_buffer_logger.py +0 -0
  77. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/loggers/_console_logger.py +0 -0
  78. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/loggers/_console_logger.pyi +0 -0
  79. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/loggers/_file_logger.py +0 -0
  80. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/loggers/_level_sin.py +0 -0
  81. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/loggers/_logger.py +0 -0
  82. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/loggers/_sub_logger.py +0 -0
  83. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/logger_manager/loggers/_sub_logger.pyi +0 -0
  84. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/logging/loggers.py +0 -0
  85. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/monitoring/__init__.py +0 -0
  86. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/monitoring/host_monitor.py +0 -0
  87. {bear_utils-0.7.19 → bear_utils-0.7.21}/src/bear_utils/time/__init__.py +0 -0
  88. {bear_utils-0.7.19 → bear_utils-0.7.21}/tests/__init__.py +0 -0
  89. {bear_utils-0.7.19 → bear_utils-0.7.21}/tests/test_add_ord_suffix.py +0 -0
  90. {bear_utils-0.7.19 → bear_utils-0.7.21}/tests/test_clipboard.py +0 -0
  91. {bear_utils-0.7.19 → bear_utils-0.7.21}/tests/test_default_shell.py +0 -0
  92. {bear_utils-0.7.19 → bear_utils-0.7.21}/tests/test_gradient.py +0 -0
  93. {bear_utils-0.7.19 → bear_utils-0.7.21}/tests/test_logger.py +0 -0
  94. {bear_utils-0.7.19 → bear_utils-0.7.21}/tests/test_platform_utils.py +0 -0
  95. {bear_utils-0.7.19 → bear_utils-0.7.21}/uv.lock +0 -0
@@ -1,5 +1,5 @@
1
1
  [bumpversion]
2
- current_version = 0.7.19
2
+ current_version = 0.7.21
3
3
 
4
4
  [bumpversion:file:pyproject.toml]
5
5
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bear-utils
3
- Version: 0.7.19
3
+ Version: 0.7.21
4
4
  Summary: Various utilities for Bear programmers, including a rich logging utility, a disk cache, and a SQLite database wrapper amongst other things.
5
5
  Author-email: chaz <bright.lid5647@fastmail.com>
6
6
  Requires-Python: >=3.12
@@ -12,7 +12,6 @@ Requires-Dist: pillow<12.0.0,>=11.2.1
12
12
  Requires-Dist: prompt-toolkit<4.0.0,>=3.0.51
13
13
  Requires-Dist: pydantic>=2.11.5
14
14
  Requires-Dist: pyglm<3.0.0,>=2.8.2
15
- Requires-Dist: pyqt6>=6.9.0
16
15
  Requires-Dist: pyyaml>=6.0.2
17
16
  Requires-Dist: rich<15.0.0,>=14.0.0
18
17
  Requires-Dist: singleton-base>=1.0.5
@@ -20,7 +19,7 @@ Requires-Dist: sqlalchemy<3.0.0,>=2.0.40
20
19
  Requires-Dist: toml>=0.10.2
21
20
  Description-Content-Type: text/markdown
22
21
 
23
- # Bear Utils v# Bear Utils v0.7.19
22
+ # Bear Utils v# Bear Utils v0.7.21
24
23
 
25
24
  Personal set of tools and utilities for Python projects, focusing on modularity and ease of use. This library includes components for caching, database management, logging, time handling, file operations, CLI prompts, image processing, clipboard interaction, gradient utilities, event systems, and async helpers.
26
25
 
@@ -1,4 +1,4 @@
1
- # Bear Utils v# Bear Utils v0.7.19
1
+ # Bear Utils v# Bear Utils v0.7.21
2
2
 
3
3
  Personal set of tools and utilities for Python projects, focusing on modularity and ease of use. This library includes components for caching, database management, logging, time handling, file operations, CLI prompts, image processing, clipboard interaction, gradient utilities, event systems, and async helpers.
4
4
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "bear-utils"
3
- version = "0.7.19"
3
+ version = "0.7.21"
4
4
  description = "Various utilities for Bear programmers, including a rich logging utility, a disk cache, and a SQLite database wrapper amongst other things."
5
5
  authors = [{ name = "chaz", email = "bright.lid5647@fastmail.com" }]
6
6
  readme = "README.md"
@@ -12,7 +12,6 @@ dependencies = [
12
12
  "pillow (>=11.2.1,<12.0.0)",
13
13
  "rich (>=14.0.0,<15.0.0)",
14
14
  "prompt-toolkit (>=3.0.51,<4.0.0)",
15
- "pyqt6>=6.9.0",
16
15
  "pydantic>=2.11.5",
17
16
  "pathspec>=0.12.1",
18
17
  "pyyaml>=6.0.2",
@@ -33,6 +32,9 @@ dev = [
33
32
  "pytest>=8.3.5",
34
33
  "twine>=6.1.0",
35
34
  ]
35
+ gui = [
36
+ "pyqt6>=6.9.0",
37
+ ]
36
38
 
37
39
  [tool.pytest.ini_options]
38
40
  markers = [
@@ -73,7 +73,15 @@ class CommandList(deque[CompletedProcess[str]]):
73
73
  class SimpleShellSession:
74
74
  """Simple shell session using subprocess with command chaining"""
75
75
 
76
- def __init__(self, env=None, cwd=None, shell: str = DEFAULT_SHELL, logger=None, verbose: bool = False):
76
+ def __init__(
77
+ self,
78
+ env=None,
79
+ cwd=None,
80
+ shell: str = DEFAULT_SHELL,
81
+ logger=None,
82
+ verbose: bool = False,
83
+ use_shell: bool = True,
84
+ ) -> None:
77
85
  self.shell: str = shell
78
86
  self.cwd: Path = Path.cwd() if cwd is None else Path(cwd)
79
87
  self.env: dict[str, str] = os.environ.copy() if env is None else env
@@ -81,6 +89,7 @@ class SimpleShellSession:
81
89
  self.previous_commands: CommandList = CommandList()
82
90
  self.result: CompletedProcess[str] | None = None
83
91
  self.verbose: bool = verbose
92
+ self.use_shell: bool = use_shell
84
93
  self.logger = self.set_logger(logger)
85
94
 
86
95
  def set_logger(self, passed_logger=None):
@@ -93,7 +102,7 @@ class SimpleShellSession:
93
102
  if BaseLogger.has_instance():
94
103
  logger = BaseLogger.get_instance().get_sub_logger(namespace="shell_session")
95
104
  else:
96
- temp = BaseLogger.get_instance(init=True)
105
+ temp: BaseLogger = BaseLogger.get_instance(init=True)
97
106
  logger: SubConsoleLogger[BaseLogger] = temp.get_sub_logger(namespace="shell_session")
98
107
  if self.verbose:
99
108
  logger.set_sub_level(VERBOSE)
@@ -137,14 +146,27 @@ class SimpleShellSession:
137
146
  """Internal method to run the accumulated command"""
138
147
  self.logger.verbose(f"Executing: {command}")
139
148
  self.next_cmd()
140
- self.result = subprocess.run(
141
- command.split(),
142
- shell=False,
143
- cwd=self.cwd,
144
- env=self.env,
145
- capture_output=True,
146
- text=True,
147
- )
149
+
150
+ if self.use_shell:
151
+ self.result = subprocess.run(
152
+ args=command,
153
+ shell=True,
154
+ cwd=self.cwd,
155
+ env=self.env,
156
+ capture_output=True,
157
+ text=True,
158
+ )
159
+ else:
160
+ command_args: list[str] = shlex.split(command)
161
+ self.result = subprocess.run(
162
+ args=command_args,
163
+ shell=False,
164
+ cwd=self.cwd,
165
+ env=self.env,
166
+ capture_output=True,
167
+ text=True,
168
+ )
169
+
148
170
  if self.result.returncode != 0:
149
171
  self.logger.error(f"Command failed with return code {self.result.returncode} {self.result.stderr.strip()}")
150
172
 
@@ -162,12 +184,12 @@ class SimpleShellSession:
162
184
  )
163
185
 
164
186
  if self.has_history and cmd is None:
165
- result = self._run(self.cmd)
187
+ result: CompletedProcess[str] | Process = self._run(self.cmd)
166
188
  elif self.empty_history and cmd is not None:
167
189
  self.cmd_buffer.write(f"{cmd} ")
168
190
  if args:
169
191
  self.cmd_buffer.write(" ".join(map(str, args)))
170
- result = self._run(self.cmd)
192
+ result: CompletedProcess[str] | Process = self._run(self.cmd)
171
193
  else:
172
194
  raise ValueError("Unexpected state")
173
195
  self.reset_buffer()
@@ -188,7 +210,14 @@ class SimpleShellSession:
188
210
  """Return the combined command as a string"""
189
211
  if not self.cmd_buffer:
190
212
  raise ValueError("No commands have been run yet")
191
- full_command: str = f"{self.shell} -c {shlex.quote(self.cmd_buffer.getvalue())}"
213
+
214
+ if self.use_shell:
215
+ # Original behavior: wrap in shell command
216
+ full_command: str = f"{self.shell} -c {shlex.quote(self.cmd_buffer.getvalue())}"
217
+ else:
218
+ # New behavior: return raw command for argument parsing
219
+ full_command: str = self.cmd_buffer.getvalue().strip()
220
+
192
221
  return full_command
193
222
 
194
223
  @property
@@ -259,8 +288,16 @@ class SimpleShellSession:
259
288
  class AsyncShellSession(SimpleShellSession):
260
289
  """Shell session using Popen for more control over the subprocess"""
261
290
 
262
- def __init__(self, env=None, cwd=None, shell: str = DEFAULT_SHELL, logger=None, verbose: bool = False):
263
- super().__init__(env=env, cwd=cwd, shell=shell, logger=logger, verbose=verbose)
291
+ def __init__(
292
+ self,
293
+ env=None,
294
+ cwd=None,
295
+ shell: str = DEFAULT_SHELL,
296
+ logger=None,
297
+ verbose: bool = False,
298
+ use_shell: bool = True,
299
+ ) -> None:
300
+ super().__init__(env=env, cwd=cwd, shell=shell, logger=logger, verbose=verbose, use_shell=use_shell)
264
301
  self.process: Process | None = None
265
302
  self._callbacks: list[Callable[[CompletedProcess], None]] = []
266
303
 
@@ -269,14 +306,27 @@ class AsyncShellSession(SimpleShellSession):
269
306
  """Run the command using Popen for better control"""
270
307
  self.logger.verbose(f"Executing: {command}")
271
308
  self.next_cmd()
272
- self.process = await asyncio.create_subprocess_shell(
273
- command,
274
- stdout=asyncio.subprocess.PIPE,
275
- stderr=asyncio.subprocess.PIPE,
276
- cwd=self.cwd,
277
- env=self.env,
278
- **kwargs,
279
- )
309
+
310
+ if self.use_shell:
311
+ self.process = await asyncio.create_subprocess_shell(
312
+ command,
313
+ stdout=asyncio.subprocess.PIPE,
314
+ stderr=asyncio.subprocess.PIPE,
315
+ cwd=self.cwd,
316
+ env=self.env,
317
+ **kwargs,
318
+ )
319
+ else:
320
+ command_args: list[str] = shlex.split(command)
321
+ self.process = await asyncio.create_subprocess_exec(
322
+ *command_args,
323
+ stdout=asyncio.subprocess.PIPE,
324
+ stderr=asyncio.subprocess.PIPE,
325
+ cwd=self.cwd,
326
+ env=self.env,
327
+ **kwargs,
328
+ )
329
+
280
330
  return self.process
281
331
 
282
332
  @override
@@ -303,10 +353,10 @@ class AsyncShellSession(SimpleShellSession):
303
353
  """Communicate with the process, sending input and waiting for completion"""
304
354
  if self.process is None:
305
355
  raise ValueError("No process has been started yet")
306
- bytes_stdin = stdin.encode("utf-8") if isinstance(stdin, str) else stdin
356
+ bytes_stdin: bytes = stdin.encode("utf-8") if isinstance(stdin, str) else stdin
307
357
 
308
358
  stdout, stderr = await self.process.communicate(input=bytes_stdin)
309
- return_code = await self.process.wait()
359
+ return_code: int = await self.process.wait()
310
360
 
311
361
  self.result = FancyCompletedProcess(
312
362
  args=self.cmd,
@@ -0,0 +1,6 @@
1
+ try:
2
+ from .gui_tools import QTApplication, get_text, select_color
3
+
4
+ __all__ = ["QTApplication", "select_color", "get_text"]
5
+ except ImportError as e:
6
+ raise ImportError("PyQt6 is required for GUI functionality. Install it with: pip install bear-utils[gui]") from e
@@ -0,0 +1,8 @@
1
+ try:
2
+ from .qt_app import QTApplication
3
+ from .qt_color_picker import select_color
4
+ from .qt_input_dialog import get_text
5
+
6
+ __all__ = ["QTApplication", "select_color", "get_text"]
7
+ except ImportError as e:
8
+ raise ImportError("PyQt6 is required for GUI functionality. Install it with: pip install bear-utils[gui]") from e
@@ -1,3 +0,0 @@
1
- from .gui_tools import QTApplication, get_text, select_color
2
-
3
- __all__ = ["QTApplication", "select_color", "get_text"]
@@ -1,5 +0,0 @@
1
- from .qt_app import QTApplication
2
- from .qt_color_picker import select_color
3
- from .qt_input_dialog import get_text
4
-
5
- __all__ = ["QTApplication", "select_color", "get_text"]
File without changes
File without changes
File without changes
File without changes
File without changes