MeUtils 2025.4.8.20.33.43__py3-none-any.whl → 2025.4.11.17.25.15__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 (43) hide show
  1. {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/METADATA +260 -260
  2. {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/RECORD +41 -38
  3. examples/_openaisdk/openai_google.py +49 -33
  4. meutils/apis/{google_apis → google}/audios.py +5 -2
  5. meutils/apis/google/chat.py +369 -0
  6. meutils/apis/google/files.py +29 -0
  7. meutils/apis/{google_apis → google}/google2openai.py +8 -4
  8. meutils/apis/google/images.py +27 -0
  9. meutils/apis/{google_apis → google}/search.py +7 -5
  10. meutils/apis/images/recraft.py +2 -4
  11. meutils/apis/jimeng/images.py +41 -8
  12. meutils/apis/search/metaso.py +2 -2
  13. meutils/apis/siliconflow/images.py +5 -3
  14. meutils/caches/acache.py +1 -1
  15. meutils/common.py +1 -0
  16. meutils/data/VERSION +1 -1
  17. meutils/decorators/catch.py +0 -8
  18. meutils/decorators/common.py +86 -19
  19. meutils/decorators/contextmanagers.py +103 -14
  20. meutils/decorators/demo.py +76 -14
  21. meutils/io/files_utils.py +2 -3
  22. meutils/io/openai_files.py +11 -6
  23. meutils/llm/check_utils.py +20 -1
  24. meutils/llm/openai_polling/__init__.py +11 -0
  25. meutils/llm/openai_polling/chat.py +45 -0
  26. meutils/{apis/google_apis → llm/openai_polling}/images.py +4 -2
  27. meutils/llm/openai_utils/common.py +1 -1
  28. meutils/notice/feishu.py +5 -2
  29. meutils/schemas/image_types.py +26 -3
  30. meutils/schemas/oneapi/common.py +12 -0
  31. meutils/schemas/openai_types.py +10 -0
  32. meutils/serving/fastapi/dependencies/__init__.py +4 -1
  33. meutils/serving/fastapi/dependencies/auth.py +10 -6
  34. meutils/serving/fastapi/exceptions/http_error.py +2 -2
  35. meutils/str_utils/__init__.py +30 -2
  36. meutils/apis/google_apis/common.py +0 -250
  37. meutils/apis/google_apis/files.py +0 -19
  38. {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/LICENSE +0 -0
  39. {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/WHEEL +0 -0
  40. {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/entry_points.txt +0 -0
  41. {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/top_level.txt +0 -0
  42. /meutils/apis/{google_apis → google}/__init__.py +0 -0
  43. /meutils/apis/{google_apis → google}/gemini_sdk.py +0 -0
@@ -33,7 +33,10 @@ from fake_useragent import UserAgent
33
33
 
34
34
  ua = UserAgent()
35
35
 
36
+ VERSION = "3.1.5"
36
37
 
38
+
39
+ #
37
40
  async def create_draft_content(request: ImageRequest, token: str):
38
41
  """
39
42
  创建草稿内容
@@ -44,7 +47,7 @@ async def create_draft_content(request: ImageRequest, token: str):
44
47
 
45
48
  request.model = MODELS_MAP.get(request.model, MODELS_MAP["default"])
46
49
 
47
- height = width = 1360
50
+ height = width = 1328
48
51
  if 'x' in request.size:
49
52
  height, width = map(int, request.size.split('x'))
50
53
 
@@ -84,7 +87,9 @@ async def create_draft_content(request: ImageRequest, token: str):
84
87
  "type": "",
85
88
  "id": str(uuid.uuid4()),
86
89
  "height": height,
87
- "width": width
90
+ "width": width,
91
+
92
+ # "resolution_type": "2k"
88
93
  },
89
94
  },
90
95
  "ability_list": [
@@ -164,7 +169,9 @@ async def create_draft_content(request: ImageRequest, token: str):
164
169
  "type": "",
165
170
  "id": str(uuid.uuid4()),
166
171
  "height": height,
167
- "width": width
172
+ "width": width,
173
+
174
+ "resolution_type": "1k"
168
175
  }
169
176
  },
170
177
  "history_option": {
@@ -181,7 +188,7 @@ async def create_draft_content(request: ImageRequest, token: str):
181
188
  "min_version": "3.0.2",
182
189
  "min_features": [],
183
190
  "is_from_tsn": True,
184
- "version": "3.0.8",
191
+ "version": VERSION,
185
192
  "main_component_id": main_component_id,
186
193
  "component_list": [component]
187
194
  }
@@ -191,8 +198,15 @@ async def create_draft_content(request: ImageRequest, token: str):
191
198
  return draft_content
192
199
 
193
200
 
201
+ def key_builder(*args, **kwargs):
202
+ logger.debug(args)
203
+ logger.debug(kwargs)
204
+
205
+ return args[1].prompt
206
+
207
+
194
208
  @retrying()
195
- @rcache(ttl=30 * 24 * 3600, serializer="pickle", key_builder=lambda *args, **kwargs: args[1].prompt)
209
+ @rcache(ttl=30 * 24 * 3600, serializer="pickle", key_builder=lambda *args, **kwargs: f"{args[1].seed} {args[1].prompt}")
196
210
  async def create_task(request: ImageRequest, token: Optional[str] = None): # todo: 图片
197
211
  token = token or await get_next_token_for_polling(FEISHU_URL, check_token)
198
212
 
@@ -229,7 +243,21 @@ async def create_task(request: ImageRequest, token: Optional[str] = None): # to
229
243
  data = response.json()
230
244
  logger.debug(bjson(data))
231
245
 
232
- if task_id := (data.get("data") or {}).get("aigc_data", {}).get("history_record_id"): # bug
246
+ # {
247
+ # "ret": "1000",
248
+ # "errmsg": "invalid parameter",
249
+ # "systime": "1744354538",
250
+ # "logid": "20250411145538E30D2FF8347A9A710F49",
251
+ # "data": {
252
+ # "aigc_data": null,
253
+ # "fail_code": "",
254
+ # "fail_starling_key": "",
255
+ # "fail_starling_message": ""
256
+ # }
257
+ # }
258
+
259
+ aigc_data = (data.get("data") or {}).get("aigc_data") or {}
260
+ if task_id := aigc_data.get("history_record_id"): # bug
233
261
  return TaskResponse(task_id=task_id, system_fingerprint=token)
234
262
  else:
235
263
 
@@ -280,7 +308,7 @@ async def get_task(task_id, token):
280
308
  "status": 50,
281
309
  """
282
310
 
283
- image_data = map(lambda x: x.get("image", {}).get("large_images"), item_list)
311
+ image_data = map(lambda x: x.get("image", {}).get("large_images", []), item_list)
284
312
 
285
313
  task_data = sum(image_data, []) | xmap_(lambda x: {"url": x.get("image_url")})
286
314
 
@@ -377,7 +405,12 @@ if __name__ == '__main__':
377
405
 
378
406
  # arun(generate(ImageRequest(prompt="fuck you")))
379
407
  prompt = "A plump Chinese beauty wearing a wedding dress revealing her skirt and underwear is swinging on the swing,Happy smile,cleavage,Exposed thighs,Spread your legs open,Extend your leg,panties,upskirt,Barefoot,sole"
380
- request = ImageRequest(prompt=prompt)
408
+ prompt = "a dog"
409
+ request = ImageRequest(prompt=prompt, size="1328x1328")
410
+ # request = ImageRequest(prompt=prompt, size="1024x1024")
411
+
412
+ # request = ImageRequest(prompt=prompt, size="2048*2048")
413
+
381
414
  # task = arun(create_task(ImageRequest(**data), token=token))
382
415
 
383
416
  # arun(get_task(task.task_id, task.system_fingerprint))
@@ -110,7 +110,7 @@ async def create(request: Union[ChatCompletionRequest, CompletionRequest]):
110
110
  _, engine_type = request.model.split(':')
111
111
 
112
112
  model = None
113
- if request.model.startswith(("meta", "deepseek")):
113
+ if request.model.startswith(("deepseek",)):
114
114
  model = "ds-r1"
115
115
  system_fingerprint = "deepseek-r1"
116
116
 
@@ -195,7 +195,7 @@ if __name__ == '__main__':
195
195
  request = ChatCompletionRequest(
196
196
  # model="deepseek-search",
197
197
  # model="deepseek-r1-search",
198
- model="meta-deepresearch",
198
+ model="11meta-deepresearch",
199
199
  # model="ai-search",
200
200
  # model="ai-search:scholar",
201
201
  # model="ai-search-pro:scholar",
@@ -25,8 +25,7 @@ from meutils.schemas.image_types import ImageRequest, FluxImageRequest, SDImageR
25
25
  FEISHU_URL = "https://xchatllm.feishu.cn/sheets/Bmjtst2f6hfMqFttbhLcdfRJnNf?sheet=3aA5dH"
26
26
  FEISHU_URL_FREE = "https://xchatllm.feishu.cn/sheets/Bmjtst2f6hfMqFttbhLcdfRJnNf?sheet=xlvlrH"
27
27
 
28
- BASE_URL = os.getenv("SILICONFLOW_BASE_URL")
29
- # BASE_URL = "https://api.siliconflow.cn/v1"
28
+ BASE_URL = "https://api.siliconflow.cn/v1"
30
29
 
31
30
  DEFAULT_MODEL = "black-forest-labs/FLUX.1-schnell"
32
31
  MODELS = {
@@ -116,6 +115,8 @@ async def generate(request: ImageRequest, api_key: Optional[str] = None):
116
115
  response = await client.images.generate(**data)
117
116
  response.model = ""
118
117
  logger.debug(response)
118
+
119
+ response.data[0].url = unquote(response.data[0].url or "")
119
120
  if request.response_format == "b64_json":
120
121
  b64_json = await to_base64(response.data[0].url)
121
122
 
@@ -162,7 +163,8 @@ if __name__ == '__main__':
162
163
  # request = FluxImageRequest(model="flux", prompt="a dog", size="1024x1024", num_inference_steps=1)
163
164
  # request = FluxImageRequest(model="flux-pro", prompt="a dog", size="10x10", num_inference_steps=1)
164
165
 
165
- data = {'model': 'flux-schnell', 'prompt': '画一个2025年电脑如何一键重装系统win10教程详解的封面图', 'n': 1, 'size': '680x400'}
166
+ data = {'model': 'flux-schnell', 'prompt': '画一个2025年电脑如何一键重装系统win10教程详解的封面图', 'n': 1,
167
+ 'size': '680x400'}
166
168
  request = FluxImageRequest(**data)
167
169
 
168
170
  print(request)
meutils/caches/acache.py CHANGED
@@ -60,7 +60,7 @@ async def cached_fc(user_id, **kwargs):
60
60
  key_builder = lambda *args, **kwargs: args[1].prompt
61
61
 
62
62
  def key_builder(*args, **kwargs):
63
- # print(args)
63
+ print(args)
64
64
  return args[1].prompt
65
65
 
66
66
 
meutils/common.py CHANGED
@@ -68,6 +68,7 @@ from queue import Queue
68
68
  from pprint import pprint
69
69
  from abc import abstractmethod
70
70
  from dataclasses import dataclass
71
+ from urllib.parse import unquote, unquote_plus, urlparse, urljoin
71
72
  from functools import reduce, lru_cache, partial
72
73
 
73
74
  from collections import Counter, OrderedDict
meutils/data/VERSION CHANGED
@@ -1 +1 @@
1
- 2025.04.08.20.33.43
1
+ 2025.04.11.17.25.15
@@ -8,7 +8,6 @@
8
8
  # @Software : PyCharm
9
9
  # @Description :
10
10
  from meutils.pipe import *
11
- from meutils.log_utils import logger4wecom
12
11
 
13
12
 
14
13
  def wecom_hook(title='Task Done', text=None, hook_url=None):
@@ -30,12 +29,6 @@ def wecom_hook(title='Task Done', text=None, hook_url=None):
30
29
 
31
30
  logger.info(f"{title} done in {mins} m")
32
31
 
33
- logger4wecom(
34
- title=title,
35
- text=f"**{wrapped.__name__}:** {r if text is None else text}\n耗时 {mins} m",
36
- hook_url=hook_url
37
- )
38
-
39
32
  return r
40
33
 
41
34
  return wrapper
@@ -54,7 +47,6 @@ def wecom_catch(hook_url=None, more_info=True):
54
47
  {info.strip()}
55
48
  ```
56
49
  """.strip()
57
- logger4wecom(wrapped.__name__, text, hook_url)
58
50
 
59
51
  return wrapper
60
52
 
@@ -7,19 +7,20 @@
7
7
  # @WeChat : 313303303
8
8
  # @Software : PyCharm
9
9
  # @Description :
10
- import importlib
11
10
  import os
12
11
  import sys
13
12
  import time
14
- from functools import wraps
15
-
13
+ import wrapt
14
+ import asyncio
15
+ import inspect
16
16
  import schedule
17
17
  import threading
18
18
  import traceback
19
- import wrapt
19
+ import importlib
20
20
 
21
21
  from loguru import logger
22
22
  from tqdm.auto import tqdm
23
+ from functools import wraps
23
24
  from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
24
25
  from contextlib import contextmanager, asynccontextmanager
25
26
  from typing import *
@@ -148,14 +149,6 @@ def do_nothing(func, *args, **kwargs):
148
149
  return func(*args, **kwargs)
149
150
 
150
151
 
151
- @decorator
152
- def try_catch(func, is_trace=False, *args, **kwargs):
153
- try:
154
- return func(*args, **kwargs)
155
- except Exception as e:
156
- return {'error': traceback.format_exc().strip() if is_trace else e}
157
-
158
-
159
152
  @decorator
160
153
  def timeout(func, seconds=1, *args, **kwargs):
161
154
  future = ThreadPoolExecutor(1).submit(func, *args, **kwargs)
@@ -398,12 +391,64 @@ def limit(limit_value: str = '1/second', key_func: Callable[..., str] = None, er
398
391
  return inner
399
392
 
400
393
 
394
+ def try_catch(
395
+ task: Optional[str] = None,
396
+ callback: Optional[Callable] = None,
397
+ is_trace: bool = False,
398
+ ):
399
+ from meutils.notice.feishu import send_message_for_try_catch
400
+
401
+ callback = callback or send_message_for_try_catch # logger.error
402
+
403
+ def decorator(func):
404
+ @wraps(func)
405
+ def wrapper(*args, **kwargs):
406
+ task_name = task or f"{func.__module__}.{func.__name__}"
407
+
408
+ data = {
409
+ "task_name": task_name,
410
+ # "args": args,
411
+ # "kwargs": kwargs,
412
+ # "defined_args": inspect.getfullargspec(func).args, # .varargs
413
+ }
414
+
415
+ logger.debug(data)
416
+
417
+ async def async_wrapper():
418
+ try:
419
+ if asyncio.iscoroutinefunction(func):
420
+ return await func(*args, **kwargs)
421
+ else:
422
+ return func(*args, **kwargs)
423
+ except Exception as e:
424
+
425
+ if is_trace:
426
+ error_msg = f"{task_name}:\n{traceback.format_exc()}"
427
+ else:
428
+ error_msg = f"{task_name}: {e}"
429
+
430
+ data["error"] = error_msg
431
+ callback(data)
432
+
433
+ raise
434
+
435
+ if asyncio.iscoroutinefunction(func):
436
+ return async_wrapper()
437
+ else:
438
+ try:
439
+ return asyncio.get_event_loop().run_until_complete(async_wrapper())
440
+ except RuntimeError:
441
+ # 如果没有事件循环(例如在同步环境中),则直接运行
442
+ return async_wrapper()
443
+
444
+ return wrapper
445
+
446
+ return decorator
401
447
 
402
448
 
403
449
  if __name__ == '__main__':
404
450
  import time
405
451
 
406
-
407
452
  # @timeout()
408
453
  # def ff():
409
454
  # import time
@@ -476,11 +521,33 @@ if __name__ == '__main__':
476
521
  # while 1:
477
522
  # pass
478
523
 
479
- def f():
480
- return 1 / 0
481
- # return 1
524
+ # def f():
525
+ # return 1 / 0
526
+ # # return 1
527
+ #
528
+ #
529
+ # with tryer('try'):
530
+ # a = f()
531
+ # print(a)
532
+
533
+ from meutils.pipe import *
534
+ from meutils.notice.feishu import send_message_for_try_catch
535
+
536
+
537
+ @try_catch(is_trace=False)
538
+ async def my_async_function(x=1, y=1):
539
+ # 您的异步函数代码
540
+ pass
541
+ 1 / 0
482
542
 
483
543
 
484
- with tryer('try'):
485
- a = f()
486
- print(a)
544
+ async def main():
545
+ await my_async_function(x=111, y=10000)
546
+
547
+
548
+ # @async_try_catch(task="Custom Task Name", fallback=some_fallback_function)
549
+ # async def another_async_function():
550
+ # # 另一个异步函数的代码
551
+ # pass
552
+
553
+ arun(main())
@@ -9,6 +9,7 @@
9
9
  # @Description :
10
10
 
11
11
  from meutils.pipe import *
12
+ from meutils.notice.feishu import send_message_for_try_catch
12
13
 
13
14
  from contextlib import contextmanager, asynccontextmanager
14
15
  from concurrent.futures import ThreadPoolExecutor, as_completed, TimeoutError
@@ -53,12 +54,13 @@ async def atry_catcher(task="Task", fallback: Callable = None, is_trace: bool =
53
54
  except Exception as e:
54
55
  error = traceback.format_exc() if is_trace else e
55
56
  logger.error(f"{task}: {error}")
57
+
56
58
  if fallback:
57
59
  yield await fallback()
58
60
 
59
61
 
60
62
  @contextmanager
61
- def timeout_task_executor(timeout: float=3, max_workers: int = None):
63
+ def timeout_task_executor(timeout: float = 3, max_workers: int = None):
62
64
  """
63
65
  一个上下文管理器,用于执行任务并设置超时时间。
64
66
  :param timeout: 超时时间(秒)。
@@ -85,6 +87,90 @@ def timeout_task_executor(timeout: float=3, max_workers: int = None):
85
87
  executor.shutdown(wait=False) # 不等待未完成的任务,直接关闭
86
88
 
87
89
 
90
+ @asynccontextmanager
91
+ async def atry_catcher(task="Task", fallback: Callable = None, is_trace: bool = False):
92
+ try:
93
+ yield
94
+ except Exception as e:
95
+ error = traceback.format_exc() if is_trace else e
96
+ logger.error(f"{task}: {error}")
97
+ if fallback:
98
+ yield await fallback()
99
+
100
+
101
+ @asynccontextmanager
102
+ async def atry_catch(
103
+ task: Optional[str] = None,
104
+ callback: Optional[Callable] = None,
105
+ is_trace: bool = False,
106
+ **kwargs,
107
+ ):
108
+ callback = callback or send_message_for_try_catch
109
+
110
+ task_name = task or "Unnamed TryCatch Task"
111
+
112
+ data = {
113
+ "task_name": task_name,
114
+ }
115
+ for k, v in kwargs.items():
116
+ if isinstance(v, BaseModel):
117
+ v = v.model_dump(exclude_none=True)
118
+ data[k] = v
119
+
120
+ # logger.debug(data)
121
+
122
+ try:
123
+ yield
124
+ except Exception as e:
125
+ if is_trace:
126
+ error_msg = f"""{traceback.format_exc()}"""
127
+ else:
128
+ error_msg = f"{e}"
129
+
130
+ data["error"] = error_msg
131
+
132
+ callback(data)
133
+ raise
134
+
135
+
136
+ @contextmanager
137
+ def try_catch(
138
+ task: Optional[str] = None,
139
+ callback: Optional[Callable] = None,
140
+ is_trace: bool = False,
141
+ **kwargs,
142
+ ):
143
+ callback = callback or send_message_for_try_catch
144
+
145
+ task_name = task or "Unnamed TryCatch Task"
146
+
147
+ data = {
148
+ "task_name": task_name,
149
+ }
150
+ for k, v in kwargs.items():
151
+ if isinstance(v, BaseModel):
152
+ v = v.model_dump(exclude_none=True)
153
+ elif isinstance(v, typing.Mapping):
154
+ v = dict(v)
155
+
156
+ data[k] = v
157
+
158
+ logger.debug(data)
159
+
160
+ try:
161
+ yield
162
+ except Exception as e:
163
+ if is_trace:
164
+ error_msg = f"""{traceback.format_exc()}"""
165
+ else:
166
+ error_msg = f"{e}"
167
+
168
+ data["error"] = error_msg
169
+
170
+ callback(data)
171
+ raise e
172
+
173
+
88
174
  if __name__ == '__main__':
89
175
  # async def f():
90
176
  # return 1/0
@@ -93,16 +179,19 @@ if __name__ == '__main__':
93
179
  # with try_catcher("test"):
94
180
  # arun(f())
95
181
 
96
- def example_task():
97
- print("Starting task...")
98
- time.sleep(4) # 模拟耗时任务
99
- print("Task completed!")
100
- return "Done"
101
-
102
-
103
- with timeout_task_executor(timeout=3) as execute:
104
- try:
105
- result = execute(example_task)
106
- print(f"Task result: {result}")
107
- except TimeoutError:
108
- print("Task did not complete in time.")
182
+ # def example_task():
183
+ # print("Starting task...")
184
+ # time.sleep(4) # 模拟耗时任务
185
+ # print("Task completed!")
186
+ # return "Done"
187
+ #
188
+ #
189
+ # with timeout_task_executor(timeout=3) as execute:
190
+ # try:
191
+ # result = execute(example_task)
192
+ # print(f"Task result: {result}")
193
+ # except TimeoutError:
194
+ # print("Task did not complete in time.")
195
+
196
+ with try_catch("test"):
197
+ 1 / 0
@@ -7,26 +7,88 @@
7
7
  # @WeChat : 313303303
8
8
  # @Software : PyCharm
9
9
  # @Description :
10
+ import asyncio
11
+ import traceback
12
+ from typing import Optional, Callable
13
+ from contextlib import asynccontextmanager, contextmanager
10
14
 
15
+ from meutils.notice.feishu import send_message_for_try_catch
11
16
 
12
- from meutils.decorators.feishu import *
13
17
 
14
- from meutils.decorators.retry import retrying
15
- import asyncio
18
+ @asynccontextmanager
19
+ async def atry_catch(
20
+ task: Optional[str] = None,
21
+ callback: Optional[Callable] = None,
22
+ is_trace: bool = False,
23
+ ):
24
+ callback = callback or send_message_for_try_catch
25
+
26
+ task_name = task or "Unnamed TryCatch Task"
27
+
28
+ data = {
29
+ "task_name": task_name,
30
+ }
31
+
32
+ # logger.debug(data)
33
+
34
+ try:
35
+ yield
36
+ except Exception as e:
37
+ if is_trace:
38
+ error_msg = f"""{task_name}:\n{traceback.format_exc()}"""
39
+ else:
40
+ error_msg = f"{task_name}: {e}"
41
+
42
+ data["error"] = error_msg
43
+
44
+ callback(data)
45
+ raise
46
+
16
47
 
17
- import openai
48
+ @contextmanager
49
+ def try_catch(
50
+ task: Optional[str] = None,
51
+ callback: Optional[Callable] = None,
52
+ is_trace: bool = False,
53
+ ):
54
+ callback = callback or send_message_for_try_catch
18
55
 
19
- @retrying
20
- async def my_coroutine_function():
21
- # 在这里执行协程函数的逻辑
22
- # 如果发生异常,tenacity将自动重试
23
- await asyncio.sleep(1)
24
- raise Exception("Something went wrong")
56
+ task_name = task or "Unnamed TryCatch Task"
57
+
58
+ data = {
59
+ "task_name": task_name,
60
+ }
61
+
62
+ # logger.debug(data)
25
63
 
26
- async def main():
27
64
  try:
28
- await my_coroutine_function()
65
+ yield
29
66
  except Exception as e:
30
- print(f"Exception: {e}")
67
+ if is_trace:
68
+ error_msg = f"""{task_name}:\n{traceback.format_exc()}"""
69
+ else:
70
+ error_msg = f"{task_name}: {e}"
71
+
72
+ data["error"] = error_msg
73
+
74
+ callback(data)
75
+ raise
76
+
77
+
78
+ if __name__ == '__main__':
79
+ from meutils.pipe import *
80
+
81
+
82
+ async def f():
83
+ return 1
84
+
85
+
86
+ async def main():
87
+ # with atry_catch_context(task="test", is_trace=True):
88
+ # 1 / 0
89
+ with try_catch(task="test", is_trace=True):
90
+ logger.debug(await f())
91
+ 1 / 0
92
+
31
93
 
32
- asyncio.run(main())
94
+ asyncio.run(main())
meutils/io/files_utils.py CHANGED
@@ -50,7 +50,6 @@ def base64_to_bytes(base64_image_string):
50
50
 
51
51
 
52
52
  @retrying()
53
- @rcache(ttl=300, serializer='pickle') # todo: UploadFile不一定兼容
54
53
  async def to_bytes(
55
54
  file: Union[UploadFile, str, bytes],
56
55
  headers: Optional[dict] = None
@@ -79,12 +78,12 @@ async def to_bytes(
79
78
  resp = await cilent.get(file)
80
79
  file_bytes = resp.content
81
80
 
82
- elif isinstance(file, str) and len(file) > 256: # base64
81
+ elif isinstance(file, str) and len(file) > 1024: # base64
83
82
  logger.debug(f"FileType: BASE64")
84
83
 
85
84
  file_bytes = base64_to_bytes(file)
86
85
 
87
- elif isinstance(file, str) and len(file) < 256 and Path(file).is_file(): # file
86
+ elif isinstance(file, str) and len(file) < 1024 and Path(file).is_file(): # file
88
87
  logger.debug(f"FileType: PATH")
89
88
 
90
89
  file_bytes = Path(file).read_bytes()
@@ -50,13 +50,15 @@ async def delete_files(client, threshold: int = 666):
50
50
 
51
51
 
52
52
  @rcache(ttl=7 * 24 * 3600)
53
- async def _file_extract(file):
53
+ async def file_extract(file):
54
54
  """
55
55
 
56
56
  :param file: url bytes path
57
57
  :return:
58
58
  """
59
59
  # url
60
+ if isinstance(file, list):
61
+ return await asyncio.gather(*map(file_extract, file))
60
62
 
61
63
  filename = Path(file).name if isinstance(file, str) else 'untitled'
62
64
  mime_type = guess_mime_type(file)
@@ -108,12 +110,14 @@ async def _file_extract(file):
108
110
  return data
109
111
 
110
112
 
111
- async def file_extract(files):
112
- if isinstance(files, str):
113
- return await _file_extract(files)
113
+ # http://admin.ilovechatgpt.top/file/boshihouyanjiurenyuankaitipingshenbiaochugaofanyidocx_88256801.docx
114
114
 
115
- tasks = [_file_extract(file) for file in files]
116
- return await asyncio.gather(*tasks)
115
+ # async def file_extract(files):
116
+ # if isinstance(files, str):
117
+ # return await _file_extract(files)
118
+ #
119
+ # tasks = [_file_extract(file) for file in files]
120
+ # return await asyncio.gather(*tasks)
117
121
 
118
122
 
119
123
  # FileObject(id='1741136989_8dd96cbee6274251b7e4c9568779bd6a', bytes=82947, created_at=1741136989, filename='kling_watermark.png', object='file', status=None, status_details=None)
@@ -153,6 +157,7 @@ if __name__ == '__main__':
153
157
  file = "http://admin.ilovechatgpt.top/file/yuzhicaizaibutongnianlingquntixiaofeixingweijishichangdiaochawenjuanweishanjianbanpptx_59787479.pptx"
154
158
  file = "https://oss.ffire.cc/files/百炼系列手机产品介绍.docx"
155
159
  # file = "https://app.yinxiang.com/fx/8b8bba1e-b254-40ff-81e1-fa3427429efe"
160
+ file = "http://admin.ilovechatgpt.top/file/boshihouyanjiurenyuankaitipingshenbiaochugaofanyidocx_88256801.docx"
156
161
 
157
162
  print(guess_mime_type(file))
158
163