Skip to content

Commit 3ab7ce3

Browse files
committed
✨ feat: contrib for tenacity
1 parent 6276c72 commit 3ab7ce3

File tree

6 files changed

+129
-22
lines changed

6 files changed

+129
-22
lines changed

example/addict_demo.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from usepy import useAdDict
2+
3+
test_dict = {
4+
"title": "test",
5+
"detail": {
6+
"authors": [
7+
"author1",
8+
"author2"
9+
],
10+
"content": "test content"
11+
}
12+
}
13+
14+
if __name__ == '__main__':
15+
d = useAdDict(test_dict)
16+
assert d.title == "test"
17+
assert d.detail.authors[0] == "author1"
18+
assert d.test == {}

example/contrib/pydantic_demo.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from usepy.contrib.pydantic_ import BaseORMModel, Field
2+
3+
if __name__ == '__main__':
4+
class Project(BaseORMModel):
5+
id: str = Field(..., path="detail.id")
6+
url: str = Field(..., path="detail.url")
7+
author_name: list = Field(..., path="detail.authors[*].name")
8+
9+
10+
test_data = {
11+
"detail": {
12+
"id": "123",
13+
"url": "https://www.baidu.com",
14+
"authors": [
15+
{"name": "张三"},
16+
{"name": "李四"},
17+
]
18+
}
19+
}
20+
project = Project.from_orm({"model": Project, "data": test_data}).dict()
21+
print(project)

example/contrib/tenacity_demo.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import asyncio
2+
from usepy.contrib.tenacity_ import retry
3+
4+
if __name__ == '__main__':
5+
@retry(max_times=3,
6+
wait_times=1,
7+
retry_on_result=None,
8+
retry_error_callback=lambda x: print("123"))
9+
def demo():
10+
print("test")
11+
return None
12+
13+
14+
@retry(max_times=3, wait_times=1, retry_on_result=None, retry_error_callback=lambda x: print("123"))
15+
async def async_demo():
16+
print("async_demo")
17+
return None
18+
19+
20+
demo()
21+
asyncio.run(async_demo())

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "usepy"
3-
version = "0.1.40"
3+
version = "0.1.41"
44
description = "usepy"
55
homepage = "https://usepy.code05.com/"
66
authors = ["miclon <jcnd@163.com>"]

src/usepy/contrib/pydantic.py renamed to src/usepy/contrib/pydantic_.py

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,3 @@ class Project(BaseORMModel):
4444
class Config:
4545
orm_mode = True
4646
getter_dict = Getter
47-
48-
49-
if __name__ == '__main__':
50-
class Project(BaseORMModel):
51-
id: str = Field(..., path="detail.id")
52-
url: str = Field(..., path="detail.url")
53-
author_name: list = Field(..., path="detail.authors[*].name")
54-
55-
56-
test_data = {
57-
"detail": {
58-
"id": "123",
59-
"url": "https://www.baidu.com",
60-
"authors": [
61-
{"name": "张三"},
62-
{"name": "李四"},
63-
]
64-
}
65-
}
66-
project = Project.from_orm({"model": Project, "data": test_data}).dict()
67-
print(project)

src/usepy/contrib/tenacity_.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import typing as t
2+
from inspect import iscoroutinefunction
3+
4+
from tenacity import (
5+
retry as _retry,
6+
stop_after_attempt, stop_never, wait_fixed,
7+
retry_if_result, retry_if_exception_type
8+
)
9+
10+
undefined = object()
11+
12+
13+
def retry(max_times: t.Optional[int] = None,
14+
wait_times: t.Optional[int] = None,
15+
retry_on_result=undefined,
16+
retry_on_exception: t.Union[
17+
t.Type[BaseException],
18+
t.Tuple[t.Type[BaseException], ...],
19+
] = Exception,
20+
*t_args, **t_kw):
21+
"""
22+
包装tenacity.retry,让调用更简易些
23+
:param max_times: 最大重试次数
24+
:param wait_times: 每次重试等待时间
25+
:param retry_on_result: 当返回值等于retry_on_result时,重试
26+
:param retry_on_exception: 当抛出指定异常时,重试
27+
:param t_args: tenacity.retry的参数
28+
:param t_kw: tenacity.retry的参数
29+
:return:
30+
"""
31+
32+
stop_on = stop_never if max_times is None else stop_after_attempt(max_times)
33+
34+
retry_on = retry_if_exception_type(retry_on_exception)
35+
if retry_on_result is not undefined:
36+
retry_on = retry_if_result(lambda result: result == retry_on_result) | retry_on
37+
38+
wait_on = wait_fixed(wait_times) if wait_times is not None else wait_fixed(0)
39+
40+
def decorator(func):
41+
42+
if iscoroutinefunction(func):
43+
@_retry(retry=retry_on, stop=stop_on, wait=wait_on, *t_args, **t_kw)
44+
async def wrapper(*args, **kwargs):
45+
return await func(*args, **kwargs)
46+
47+
return wrapper
48+
49+
else:
50+
@_retry(retry=retry_on, stop=stop_on, wait=wait_on, *t_args, **t_kw)
51+
def wrapper(*args, **kwargs):
52+
return func(*args, **kwargs)
53+
54+
return wrapper
55+
56+
return decorator
57+
58+
59+
if __name__ == '__main__':
60+
@retry(max_times=3, wait_times=1, retry_on_result=None, retry_error_callback=lambda x: print("123"))
61+
async def maybe_none():
62+
print("111111")
63+
return None
64+
65+
66+
import asyncio
67+
68+
asyncio.run(maybe_none())

0 commit comments

Comments
 (0)