bear-utils 0.8.16__py3-none-any.whl → 0.8.17__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.
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
|
+
import asyncio
|
5
6
|
from collections.abc import Callable
|
6
7
|
import json
|
7
8
|
from subprocess import CompletedProcess
|
@@ -10,9 +11,10 @@ from typing import Any, Literal, Self, overload
|
|
10
11
|
|
11
12
|
from pydantic import BaseModel, Field, field_validator
|
12
13
|
|
14
|
+
from bear_utils.extras._async_helpers import is_async_function
|
13
15
|
from bear_utils.logger_manager import (
|
14
|
-
AsyncLoggerProtocol,
|
15
|
-
LoggerProtocol,
|
16
|
+
AsyncLoggerProtocol,
|
17
|
+
LoggerProtocol,
|
16
18
|
)
|
17
19
|
|
18
20
|
SUCCESS: list[str] = ["name", "success"]
|
@@ -202,43 +204,47 @@ class FunctionResponse(BaseModel):
|
|
202
204
|
self.add(content=content, error=error, returncode=returncode or 1, **kwargs)
|
203
205
|
return self
|
204
206
|
|
205
|
-
def _add_item(self, item: str, target_list: list[str]) -> None:
|
207
|
+
async def _add_item(self, item: str, target_list: list[str]) -> None:
|
206
208
|
"""Append an item to the target list if not empty."""
|
207
209
|
if item != "":
|
208
210
|
target_list.append(item)
|
209
211
|
|
210
|
-
def _add_to_list(self, items: str | list[str], target_list: list[str], name: str | None = None) -> None:
|
212
|
+
async def _add_to_list(self, items: str | list[str], target_list: list[str], name: str | None = None) -> None:
|
211
213
|
"""Append items to the target list with optional name prefix."""
|
212
214
|
try:
|
213
215
|
if isinstance(items, list):
|
214
216
|
for item in items:
|
215
|
-
self._add_item(f"{name}: {item}" if name else item, target_list)
|
217
|
+
await self._add_item(f"{name}: {item}" if name else item, target_list)
|
216
218
|
elif isinstance(items, str):
|
217
|
-
self._add_item(f"{name}: {items}" if name else items, target_list)
|
219
|
+
await self._add_item(f"{name}: {items}" if name else items, target_list)
|
218
220
|
except Exception as e:
|
219
221
|
raise ValueError(f"Failed to add items: {e!s}") from e
|
220
222
|
|
221
|
-
def _add_content(self, content: str | list[str], name: str | None = None) -> None:
|
223
|
+
async def _add_content(self, content: str | list[str], name: str | None = None) -> None:
|
222
224
|
"""Append content to the existing content."""
|
223
|
-
self._add_to_list(content, self.content, name)
|
225
|
+
await self._add_to_list(content, self.content, name)
|
224
226
|
|
225
|
-
def _add_error(self, error: str | list[str], name: str | None = None) -> None:
|
227
|
+
async def _add_error(self, error: str | list[str], name: str | None = None) -> None:
|
226
228
|
"""Append error to the existing error."""
|
227
|
-
self._add_to_list(error, self.error, name)
|
229
|
+
await self._add_to_list(error, self.error, name)
|
228
230
|
|
229
|
-
def _handle_function_response(self, func_response: FunctionResponse) -> None:
|
231
|
+
async def _handle_function_response(self, func_response: FunctionResponse) -> None:
|
230
232
|
"""Handle a FunctionResponse object and update the current response."""
|
231
233
|
if func_response.extra:
|
232
234
|
self.extra.update(func_response.extra)
|
233
|
-
self._add_error(error=func_response.error, name=func_response.name)
|
234
|
-
self._add_content(content=func_response.content, name=func_response.name)
|
235
|
+
await self._add_error(error=func_response.error, name=func_response.name)
|
236
|
+
await self._add_content(content=func_response.content, name=func_response.name)
|
235
237
|
|
236
|
-
def _handle_completed_process(self, result: CompletedProcess[str]) -> None:
|
238
|
+
async def _handle_completed_process(self, result: CompletedProcess[str]) -> None:
|
237
239
|
"""Handle a CompletedProcess object and update the FunctionResponse."""
|
238
|
-
self._add_content(content=result.stdout.strip() if result.stdout else "")
|
239
|
-
self._add_error(error=result.stderr.strip() if result.stderr else "")
|
240
|
+
await self._add_content(content=result.stdout.strip() if result.stdout else "")
|
241
|
+
await self._add_error(error=result.stderr.strip() if result.stderr else "")
|
240
242
|
self.returncode = result.returncode
|
241
243
|
|
244
|
+
@staticmethod
|
245
|
+
async def _run_coroutines(coroutines: list[asyncio._CoroutineLike]) -> None:
|
246
|
+
await asyncio.gather(*coroutines)
|
247
|
+
|
242
248
|
def add(
|
243
249
|
self,
|
244
250
|
content: list[str] | str | FunctionResponse | CompletedProcess | None = None,
|
@@ -247,62 +253,56 @@ class FunctionResponse(BaseModel):
|
|
247
253
|
log_output: bool = False,
|
248
254
|
extra: dict[str, Any] | None = None,
|
249
255
|
) -> Self:
|
250
|
-
"""Append additional content to the existing content.
|
251
|
-
|
252
|
-
Args:
|
253
|
-
content (list[str] | str | FunctionResponse | CompletedProcess): The content to add.
|
254
|
-
error (str | list[str] | None): The error message(s) to add.
|
255
|
-
returncode (int | None): The return code of the function call.
|
256
|
-
log_output (bool): Whether to log the output using the logger.
|
257
|
-
**kwargs: Additional metadata to include in the response.
|
258
|
-
|
259
|
-
Returns:
|
260
|
-
Self: The updated FunctionResponse instance.
|
261
|
-
"""
|
256
|
+
"""Append additional content to the existing content."""
|
257
|
+
coroutines: list[asyncio._CoroutineLike] = []
|
262
258
|
try:
|
263
259
|
match content:
|
264
260
|
case FunctionResponse():
|
265
|
-
self._handle_function_response(func_response=content)
|
261
|
+
coroutines.append(self._handle_function_response(func_response=content))
|
266
262
|
self.number_of_tasks += 1
|
267
263
|
case CompletedProcess():
|
268
|
-
self._handle_completed_process(result=content)
|
264
|
+
coroutines.append(self._handle_completed_process(result=content))
|
269
265
|
self.number_of_tasks += 1
|
270
266
|
case str() | list() if content:
|
271
|
-
self._add_content(content=content)
|
267
|
+
coroutines.append(self._add_content(content=content))
|
272
268
|
self.number_of_tasks += 1
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
self.
|
280
|
-
|
281
|
-
|
269
|
+
if isinstance(error, (str | list)):
|
270
|
+
coroutines.append(self._add_error(error=error))
|
271
|
+
if returncode is not None:
|
272
|
+
self.returncode = returncode
|
273
|
+
if isinstance(extra, dict):
|
274
|
+
self.extra.update(extra)
|
275
|
+
if log_output and self.logger and (content or error):
|
276
|
+
coroutines.append(self._log_handling(content=content, error=error, logger=self.logger))
|
277
|
+
if coroutines:
|
278
|
+
asyncio.run(self._run_coroutines(coroutines))
|
282
279
|
except Exception as e:
|
283
280
|
raise ValueError(f"Failed to add content: {e!s}") from e
|
284
281
|
return self
|
285
282
|
|
286
|
-
def _log_handling(
|
283
|
+
async def _log_handling(
|
287
284
|
self,
|
288
285
|
content: list[str] | str | FunctionResponse | CompletedProcess | None,
|
289
286
|
error: str | list[str] | None,
|
290
|
-
logger: LoggerProtocol,
|
287
|
+
logger: LoggerProtocol | AsyncLoggerProtocol,
|
291
288
|
) -> None:
|
292
289
|
"""Log the content and error messages if they exist."""
|
293
290
|
|
294
|
-
def _log_messages(messages: str | list[str], log_func: Callable) -> None:
|
291
|
+
async def _log_messages(messages: str | list[str], log_func: Callable) -> None:
|
295
292
|
if isinstance(messages, str):
|
296
293
|
messages = [messages]
|
297
294
|
if isinstance(messages, list):
|
298
295
|
for msg in messages:
|
299
|
-
|
296
|
+
if is_async_function(log_func):
|
297
|
+
await log_func(f"{self.name}: {msg}" if self.name else msg)
|
298
|
+
else:
|
299
|
+
log_func(f"{self.name}: {msg}" if self.name else msg)
|
300
300
|
|
301
301
|
if content and isinstance(content, (str | list)):
|
302
|
-
_log_messages(content, logger.info)
|
302
|
+
await _log_messages(content, logger.info)
|
303
303
|
|
304
304
|
if error and isinstance(error, (str | list)):
|
305
|
-
_log_messages(error, logger.error)
|
305
|
+
await _log_messages(error, logger.error)
|
306
306
|
|
307
307
|
@overload
|
308
308
|
def done(self, to_dict: Literal[True], suppress: list[str] | None = None) -> dict[str, Any]: ...
|
@@ -365,8 +365,11 @@ if __name__ == "__main__":
|
|
365
365
|
# Example usage
|
366
366
|
from rich import inspect
|
367
367
|
|
368
|
-
|
369
|
-
|
368
|
+
from bear_utils.logger_manager import SimpleLogger
|
369
|
+
|
370
|
+
response = FunctionResponse(name="example_function", logger=SimpleLogger())
|
371
|
+
|
372
|
+
response.add(content="This is a test content.", error="This is an error message.", log_output=True)
|
370
373
|
|
371
374
|
inspect(response)
|
372
375
|
print(response)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: bear-utils
|
3
|
-
Version: 0.8.
|
3
|
+
Version: 0.8.17
|
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
|
@@ -22,7 +22,7 @@ Requires-Dist: toml>=0.10.2
|
|
22
22
|
Requires-Dist: uvicorn>=0.35.0
|
23
23
|
Description-Content-Type: text/markdown
|
24
24
|
|
25
|
-
# Bear Utils v# Bear Utils v0.8.
|
25
|
+
# Bear Utils v# Bear Utils v0.8.17
|
26
26
|
|
27
27
|
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.
|
28
28
|
|
@@ -37,7 +37,7 @@ bear_utils/extras/_async_helpers.py,sha256=cxq5d24NHkECmZqTVXEazv6K-XUa7skFnX6KQ
|
|
37
37
|
bear_utils/extras/_tools.py,sha256=-rOH_-0pRd7_-o_l2QqByYBB2yhbXcTC8fuQf4Sx-eg,7671
|
38
38
|
bear_utils/extras/platform_utils.py,sha256=Ai7ow7S-_cKb5zFwFh8dkC8xmbMJFy-0_-w3NCERdEw,1362
|
39
39
|
bear_utils/extras/responses/__init__.py,sha256=XbE4VKemrKRwx9E5jqy__OiM_AAjA58ebnqQ2hytnT0,225
|
40
|
-
bear_utils/extras/responses/function_response.py,sha256=
|
40
|
+
bear_utils/extras/responses/function_response.py,sha256=ZOJzb3N1NmsQHmX5-9MKPlkwbb4LkljQunE1TK5IhsA,15408
|
41
41
|
bear_utils/extras/wrappers/__init__.py,sha256=crh4sKOLvuhNMVX5bJYjCFWtXtH7G47UgNPOHq3HXTk,43
|
42
42
|
bear_utils/extras/wrappers/add_methods.py,sha256=z2XZG2ZoYOB1MaGiLli4NRyyTeRgBy7tuYsiy8mTa9s,4422
|
43
43
|
bear_utils/files/__init__.py,sha256=mIdnFSXoDE64ElM43bN2m6KuafURnN82ki0pdqN8q2o,201
|
@@ -86,6 +86,6 @@ bear_utils/monitoring/__init__.py,sha256=9DKNIWTp_voLnaWgiP-wJ-o_N0hYixo-MzjUmg8
|
|
86
86
|
bear_utils/monitoring/_common.py,sha256=LYQFxgTP9fk0cH71IQTuGwBYYPWCqHP_mMRNecoD76M,657
|
87
87
|
bear_utils/monitoring/host_monitor.py,sha256=e0TYRJw9iDj5Ga6y3ck1TBFEeH42Cax5mQYaNU8yams,13241
|
88
88
|
bear_utils/time/__init__.py,sha256=VctjJG17SyEHAFXytI1sZrOrq7zm3hVenIDOJFdaMN0,1424
|
89
|
-
bear_utils-0.8.
|
90
|
-
bear_utils-0.8.
|
91
|
-
bear_utils-0.8.
|
89
|
+
bear_utils-0.8.17.dist-info/METADATA,sha256=95W22Dt-rATJiRWx_UarSfDWp4R1jxlLq75ks3BQLqE,8699
|
90
|
+
bear_utils-0.8.17.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
91
|
+
bear_utils-0.8.17.dist-info/RECORD,,
|
File without changes
|