bear-utils 0.7.19__py3-none-any.whl → 0.7.21__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.
@@ -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,
@@ -1,3 +1,6 @@
1
- from .gui_tools import QTApplication, get_text, select_color
1
+ try:
2
+ from .gui_tools import QTApplication, get_text, select_color
2
3
 
3
- __all__ = ["QTApplication", "select_color", "get_text"]
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
@@ -1,5 +1,8 @@
1
- from .qt_app import QTApplication
2
- from .qt_color_picker import select_color
3
- from .qt_input_dialog import get_text
1
+ try:
2
+ from .qt_app import QTApplication
3
+ from .qt_color_picker import select_color
4
+ from .qt_input_dialog import get_text
4
5
 
5
- __all__ = ["QTApplication", "select_color", "get_text"]
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,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
 
@@ -11,7 +11,7 @@ bear_utils/cli/commands.py,sha256=2uVYhU3qXdpkmQ3gKaUgsplfJMpEVxVGvdnJl-3H7to,28
11
11
  bear_utils/cli/prompt_helpers.py,sha256=aGfa4tnO24kFKC-CBJhoiKtll8kc_uU5RvXmxSoD5BM,6094
12
12
  bear_utils/cli/shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  bear_utils/cli/shell/_base_command.py,sha256=4VsInKhWRSzPyllnXXdueCDKwJz6i7ioZP1bZN-K5T4,2360
14
- bear_utils/cli/shell/_base_shell.py,sha256=ztJ7c3KbSqwva0UFaQM0kNN7SMx5qdFLbklIL1Mwr_8,14562
14
+ bear_utils/cli/shell/_base_shell.py,sha256=mw88NctENj47VzWtRX0eoTdBku_KTYUnNfZrDeevft4,15941
15
15
  bear_utils/cli/shell/_common.py,sha256=_KQyL5lvqOfjonFIwlEOyp3K9G3TSOj19RhgVzfNNpg,669
16
16
  bear_utils/config/__init__.py,sha256=htYbcAhIAGXgA4BaSQMKRtwu5RjWwNsnAiD0JxZ82aE,289
17
17
  bear_utils/config/config_manager.py,sha256=WojWwxsTo2Izf2EFxZJXjjUmhqcbbatZ-nBKq436BGw,2631
@@ -46,8 +46,8 @@ bear_utils/files/file_handlers/yaml_file_handler.py,sha256=Oe8U0fYtDv7q8sFWs_rO3
46
46
  bear_utils/graphics/__init__.py,sha256=N6EXOyAVoytsKecFKvi4P9Q0biEZeLkLBDor5YFUqYg,218
47
47
  bear_utils/graphics/bear_gradient.py,sha256=bwjJobhgMguEA0FQnjpGzyU3CzFG4bxEvxJtJXAKBcc,4808
48
48
  bear_utils/graphics/image_helpers.py,sha256=fy96H_BkuiCXecDXCMmrlH-SWGsA5SkEUSxlKGzcibI,1374
49
- bear_utils/gui/__init__.py,sha256=PUxxVf4txMQhzwXQlCn9SJfZgIxnOZJdJ_ADO8W5EdI,118
50
- bear_utils/gui/gui_tools/__init__.py,sha256=RItgVR6gVL0tmWF9KLmZaKKiu-DMgRwvNSOAHhbE0QM,171
49
+ bear_utils/gui/__init__.py,sha256=fCq-WDA5w5lx2Lg7V5_zsYyBKV88gnStPRQSZcUqWjw,274
50
+ bear_utils/gui/gui_tools/__init__.py,sha256=3iHLnm5lv7GVTvTiZ9MazLYtseK8-b2dYZmHRV3YuKw,335
51
51
  bear_utils/gui/gui_tools/_settings.py,sha256=1zFSMwTacybbleXs2LMDuoyZJwr8ixkLZBfcYVfLbiU,1202
52
52
  bear_utils/gui/gui_tools/_types.py,sha256=krguJ-ccALKeUHz9auh_iyOCzeAuerOYcuhWW8jjJQ0,248
53
53
  bear_utils/gui/gui_tools/qt_app.py,sha256=rTeiaGSZztKogZC1E6lDwOfJ0eVcZXWJmNGjOkbT9bw,5520
@@ -74,6 +74,6 @@ bear_utils/logging/logger_manager/loggers/_sub_logger.pyi,sha256=-SCh73lTkqolDq-
74
74
  bear_utils/monitoring/__init__.py,sha256=cj7UYsipfYFwxQmXtMpziAv4suRtGzWEdjdwOCbxJN4,168
75
75
  bear_utils/monitoring/host_monitor.py,sha256=GwIK9X8rATUhYIbOXi4MINfACWgO3T1vzUK1gSK_TQc,12902
76
76
  bear_utils/time/__init__.py,sha256=EHzc9KiGG3l6mAPhiIeFcYqxQG_w0QQ1ES3yRFVr8ug,721
77
- bear_utils-0.7.19.dist-info/METADATA,sha256=Glrqqmgl8j9nDgJEn7ljiq6Ur8p2oCYSspToAZ4tvh0,7326
78
- bear_utils-0.7.19.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
79
- bear_utils-0.7.19.dist-info/RECORD,,
77
+ bear_utils-0.7.21.dist-info/METADATA,sha256=Zycfs1dpb1uMnV_P2tjgDIs-S8k2npsmOA4RJ-PWct8,7298
78
+ bear_utils-0.7.21.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
79
+ bear_utils-0.7.21.dist-info/RECORD,,