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.
- {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/METADATA +260 -260
- {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/RECORD +41 -38
- examples/_openaisdk/openai_google.py +49 -33
- meutils/apis/{google_apis → google}/audios.py +5 -2
- meutils/apis/google/chat.py +369 -0
- meutils/apis/google/files.py +29 -0
- meutils/apis/{google_apis → google}/google2openai.py +8 -4
- meutils/apis/google/images.py +27 -0
- meutils/apis/{google_apis → google}/search.py +7 -5
- meutils/apis/images/recraft.py +2 -4
- meutils/apis/jimeng/images.py +41 -8
- meutils/apis/search/metaso.py +2 -2
- meutils/apis/siliconflow/images.py +5 -3
- meutils/caches/acache.py +1 -1
- meutils/common.py +1 -0
- meutils/data/VERSION +1 -1
- meutils/decorators/catch.py +0 -8
- meutils/decorators/common.py +86 -19
- meutils/decorators/contextmanagers.py +103 -14
- meutils/decorators/demo.py +76 -14
- meutils/io/files_utils.py +2 -3
- meutils/io/openai_files.py +11 -6
- meutils/llm/check_utils.py +20 -1
- meutils/llm/openai_polling/__init__.py +11 -0
- meutils/llm/openai_polling/chat.py +45 -0
- meutils/{apis/google_apis → llm/openai_polling}/images.py +4 -2
- meutils/llm/openai_utils/common.py +1 -1
- meutils/notice/feishu.py +5 -2
- meutils/schemas/image_types.py +26 -3
- meutils/schemas/oneapi/common.py +12 -0
- meutils/schemas/openai_types.py +10 -0
- meutils/serving/fastapi/dependencies/__init__.py +4 -1
- meutils/serving/fastapi/dependencies/auth.py +10 -6
- meutils/serving/fastapi/exceptions/http_error.py +2 -2
- meutils/str_utils/__init__.py +30 -2
- meutils/apis/google_apis/common.py +0 -250
- meutils/apis/google_apis/files.py +0 -19
- {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/LICENSE +0 -0
- {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/WHEEL +0 -0
- {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/entry_points.txt +0 -0
- {MeUtils-2025.4.8.20.33.43.dist-info → MeUtils-2025.4.11.17.25.15.dist-info}/top_level.txt +0 -0
- /meutils/apis/{google_apis → google}/__init__.py +0 -0
- /meutils/apis/{google_apis → google}/gemini_sdk.py +0 -0
meutils/apis/jimeng/images.py
CHANGED
@@ -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 =
|
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":
|
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
|
-
|
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
|
-
|
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))
|
meutils/apis/search/metaso.py
CHANGED
@@ -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(("
|
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="
|
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 =
|
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,
|
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
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.
|
1
|
+
2025.04.11.17.25.15
|
meutils/decorators/catch.py
CHANGED
@@ -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
|
|
meutils/decorators/common.py
CHANGED
@@ -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
|
-
|
15
|
-
|
13
|
+
import wrapt
|
14
|
+
import asyncio
|
15
|
+
import inspect
|
16
16
|
import schedule
|
17
17
|
import threading
|
18
18
|
import traceback
|
19
|
-
import
|
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
|
-
|
481
|
-
|
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
|
-
|
485
|
-
|
486
|
-
|
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
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
with timeout_task_executor(timeout=3) as execute:
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
meutils/decorators/demo.py
CHANGED
@@ -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
|
-
|
15
|
-
|
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
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
-
|
65
|
+
yield
|
29
66
|
except Exception as e:
|
30
|
-
|
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) >
|
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) <
|
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()
|
meutils/io/openai_files.py
CHANGED
@@ -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
|
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
|
-
|
112
|
-
if isinstance(files, str):
|
113
|
-
return await _file_extract(files)
|
113
|
+
# http://admin.ilovechatgpt.top/file/boshihouyanjiurenyuankaitipingshenbiaochugaofanyidocx_88256801.docx
|
114
114
|
|
115
|
-
|
116
|
-
|
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
|
|