Skip to content

Commit d502eaa

Browse files
committed
@sanderegg review: moving to async_tools
1 parent f94a1e0 commit d502eaa

File tree

5 files changed

+48
-43
lines changed

5 files changed

+48
-43
lines changed

packages/common-library/src/common_library/async_tools.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import asyncio
2+
import datetime
23
import functools
34
import logging
4-
from collections.abc import Awaitable, Callable
5+
from collections.abc import Awaitable, Callable, Coroutine
56
from concurrent.futures import Executor
7+
from functools import wraps
68
from inspect import isawaitable
7-
from typing import ParamSpec, TypeVar, overload
9+
from typing import Any, ParamSpec, TypeVar, overload
810

911
_logger = logging.getLogger(__name__)
1012

@@ -110,3 +112,21 @@ async def cancel_and_wait(
110112
"Task %s cancellation is complete",
111113
task.get_name(),
112114
)
115+
116+
117+
def delayed_start(
118+
delay: datetime.timedelta,
119+
) -> Callable[
120+
[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]
121+
]:
122+
def _decorator(
123+
func: Callable[P, Coroutine[Any, Any, R]],
124+
) -> Callable[P, Coroutine[Any, Any, R]]:
125+
@wraps(func)
126+
async def _wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
127+
await asyncio.sleep(delay.total_seconds())
128+
return await func(*args, **kwargs)
129+
130+
return _wrapper
131+
132+
return _decorator

packages/common-library/tests/test_async_tools.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import asyncio
22
import time
33
from concurrent.futures import ThreadPoolExecutor
4+
from datetime import timedelta
45
from typing import Any
56

67
import pytest
7-
from common_library.async_tools import cancel_and_wait, make_async, maybe_await
8+
from common_library.async_tools import (
9+
cancel_and_wait,
10+
delayed_start,
11+
make_async,
12+
maybe_await,
13+
)
814

915

1016
@make_async()
@@ -193,3 +199,20 @@ async def slow_cleanup_coro():
193199
) # 0.2 seconds < 2 seconds cleanup
194200

195201
assert task.cancelled()
202+
203+
204+
async def test_with_delay():
205+
@delayed_start(timedelta(seconds=0.2))
206+
async def decorated_awaitable() -> int:
207+
return 42
208+
209+
assert await decorated_awaitable() == 42
210+
211+
async def another_awaitable() -> int:
212+
return 42
213+
214+
decorated_another_awaitable = delayed_start(timedelta(seconds=0.2))(
215+
another_awaitable
216+
)
217+
218+
assert await decorated_another_awaitable() == 42

packages/service-library/src/servicelib/async_utils.py

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import asyncio
2-
import datetime
32
import logging
43
from collections import deque
5-
from collections.abc import Awaitable, Callable, Coroutine
4+
from collections.abc import Awaitable, Callable
65
from contextlib import suppress
76
from dataclasses import dataclass
87
from functools import wraps
@@ -211,21 +210,3 @@ async def worker(in_q: Queue[QueueElement], out_q: Queue) -> None:
211210
return wrapper
212211

213212
return decorator
214-
215-
216-
def delayed_start(
217-
delay: datetime.timedelta,
218-
) -> Callable[
219-
[Callable[P, Coroutine[Any, Any, R]]], Callable[P, Coroutine[Any, Any, R]]
220-
]:
221-
def _decorator(
222-
func: Callable[P, Coroutine[Any, Any, R]],
223-
) -> Callable[P, Coroutine[Any, Any, R]]:
224-
@wraps(func)
225-
async def _wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
226-
await asyncio.sleep(delay.total_seconds())
227-
return await func(*args, **kwargs)
228-
229-
return _wrapper
230-
231-
return _decorator

packages/service-library/src/servicelib/background_task.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
from collections.abc import AsyncIterator, Awaitable, Callable, Coroutine
77
from typing import Any, Final, ParamSpec, TypeVar
88

9+
from common_library.async_tools import cancel_and_wait, delayed_start
910
from tenacity import TryAgain, before_sleep_log, retry, retry_if_exception_type
1011
from tenacity.wait import wait_fixed
1112

12-
from .async_utils import cancel_and_wait, delayed_start
1313
from .logging_utils import log_catch, log_context
1414

1515
_logger = logging.getLogger(__name__)

packages/service-library/tests/test_async_utils.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@
77
import random
88
from collections import deque
99
from dataclasses import dataclass
10-
from datetime import timedelta
1110
from time import time
1211
from typing import Any
1312

1413
import pytest
1514
from faker import Faker
1615
from servicelib.async_utils import (
1716
_sequential_jobs_contexts,
18-
delayed_start,
1917
run_sequentially_in_context,
2018
)
2119

@@ -225,20 +223,3 @@ async def test_multiple_context_calls(context_param: int) -> int:
225223
assert i == await test_multiple_context_calls(i)
226224

227225
assert len(_sequential_jobs_contexts) == RETRIES
228-
229-
230-
async def test_with_delay():
231-
@delayed_start(timedelta(seconds=0.2))
232-
async def decorated_awaitable() -> int:
233-
return 42
234-
235-
assert await decorated_awaitable() == 42
236-
237-
async def another_awaitable() -> int:
238-
return 42
239-
240-
decorated_another_awaitable = delayed_start(timedelta(seconds=0.2))(
241-
another_awaitable
242-
)
243-
244-
assert await decorated_another_awaitable() == 42

0 commit comments

Comments
 (0)