tools (utils): Add aio_func attribute to @aio decorated methods:
We sometimes to need to call another method in asyncio context when we already are in this context. With the `@aio` decorator which makes the method return a `Deferred`, it was necessary to use a ping pong between `Deferred` and `Future`. This patch adds a `aio_func` attribute which directly returns the wrapped asyncio method, so it can now be awaited directly.
This commit is contained in:
parent
610eac0718
commit
b7b5797262
2 changed files with 22 additions and 19 deletions
|
|
@ -1254,25 +1254,23 @@ class Storage:
|
|||
if create_kwargs is None:
|
||||
create_kwargs = {}
|
||||
try:
|
||||
return await as_future(
|
||||
self.set_pubsub_node(client, service, name, **create_kwargs)
|
||||
return await self.set_pubsub_node.aio_func(
|
||||
client, service, name, **create_kwargs
|
||||
)
|
||||
except IntegrityError as e:
|
||||
if "unique" in str(e.orig).lower():
|
||||
# the node may already exist, if it has been created just after
|
||||
# get_pubsub_node above
|
||||
log.debug("ignoring UNIQUE constraint error")
|
||||
return await as_future(
|
||||
self.get_pubsub_node(
|
||||
client,
|
||||
service,
|
||||
name=name,
|
||||
with_items=with_items,
|
||||
with_subscriptions=with_subscriptions,
|
||||
with_affiliations=with_affiliations,
|
||||
with_parent=with_parent,
|
||||
with_link=with_link,
|
||||
)
|
||||
return await self.get_pubsub_node.aio_func(
|
||||
client,
|
||||
service,
|
||||
name=name,
|
||||
with_items=with_items,
|
||||
with_subscriptions=with_subscriptions,
|
||||
with_affiliations=with_affiliations,
|
||||
with_parent=with_parent,
|
||||
with_link=with_link,
|
||||
)
|
||||
else:
|
||||
raise e
|
||||
|
|
@ -2059,7 +2057,7 @@ class Storage:
|
|||
If affiliation is None, the entity's affiliation is removed.
|
||||
@raise exceptions.NotFound: Node doesn't exist.
|
||||
"""
|
||||
node = await as_future(self.get_pubsub_node(client, service, node_name))
|
||||
node = await self.get_pubsub_node.aio_func(client, service, node_name)
|
||||
if node is None:
|
||||
raise exceptions.NotFound(f"Node {node_name!r} not found")
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
"""various useful methods"""
|
||||
|
||||
from typing import Any, Optional, Union
|
||||
from typing import Any, Callable, Optional, Union
|
||||
import unicodedata
|
||||
import os.path
|
||||
import datetime
|
||||
|
|
@ -134,15 +134,20 @@ async def maybe_async(ret: Any) -> Any:
|
|||
return ret
|
||||
|
||||
|
||||
def aio(func):
|
||||
"""Decorator to return a Deferred from asyncio coroutine
|
||||
def aio(func: Callable[..., Any]) -> Callable[..., Any]:
|
||||
"""Decorator to return a Deferred from asyncio coroutine.
|
||||
|
||||
Functions with this decorator are run in asyncio context
|
||||
Functions with this decorator are run in asyncio context.
|
||||
|
||||
The original coroutine is exposed as func.aio_func for direct awaiting (e.g. when
|
||||
called from another @aio function to avoid spawning an extra task via ensure_future).
|
||||
"""
|
||||
|
||||
def wrapper(*args, **kwargs):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args: Any, **kwargs: Any) -> defer.Deferred:
|
||||
return defer.Deferred.fromFuture(asyncio.ensure_future(func(*args, **kwargs)))
|
||||
|
||||
wrapper.aio_func = func # type: ignore
|
||||
return wrapper
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue