Skip to content

Commit

Permalink
feat: cythonize _helpers.py (#402)
Browse files Browse the repository at this point in the history
  • Loading branch information
BobTheBuidler authored Nov 20, 2024
1 parent 4c4f85d commit 2ef1091
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 25 deletions.
2 changes: 2 additions & 0 deletions a_sync/a_sync/_helpers.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cpdef object _await(object awaitable)
cdef object _asyncify(object func, object executor)
3 changes: 3 additions & 0 deletions a_sync/a_sync/_helpers.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from a_sync._typing import *
from a_sync import exceptions as exceptions
def _await(awaitable: Awaitable[T]) -> T:...
14 changes: 8 additions & 6 deletions a_sync/a_sync/_helpers.py → a_sync/a_sync/_helpers.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

import asyncio
import functools
from concurrent.futures import Executor

import a_sync.asyncio
from a_sync import exceptions
from a_sync._typing import *

cdef object get_event_loop = a_sync.asyncio.get_event_loop

def _await(awaitable: Awaitable[T]) -> T:
cpdef object _await(object awaitable):
"""
Await an awaitable object in a synchronous context.
Expand All @@ -34,14 +34,14 @@ def _await(awaitable: Awaitable[T]) -> T:
- :func:`asyncio.run`: For running the main entry point of an asyncio program.
"""
try:
return a_sync.asyncio.get_event_loop().run_until_complete(awaitable)
return get_event_loop().run_until_complete(awaitable)
except RuntimeError as e:
if str(e) == "This event loop is already running":
raise exceptions.SyncModeInAsyncContextError from None
raise


def _asyncify(func: SyncFn[P, T], executor: Executor) -> CoroFn[P, T]: # type: ignore [misc]
cdef object _asyncify(object func, object executor): # type: ignore [misc]
"""
Convert a synchronous function to a coroutine function using an executor.
Expand Down Expand Up @@ -80,12 +80,14 @@ def _asyncify(func: SyncFn[P, T], executor: Executor) -> CoroFn[P, T]: # type:

if asyncio.iscoroutinefunction(func) or isinstance(func, ASyncFunction):
raise exceptions.FunctionNotSync(func)

cdef object sumbit = executor.submit

@functools.wraps(func)
async def _asyncify_wrap(*args: P.args, **kwargs: P.kwargs) -> T:
return await asyncio.futures.wrap_future(
executor.submit(func, *args, **kwargs),
loop=a_sync.asyncio.get_event_loop(),
submit(func, *args, **kwargs),
loop=get_event_loop(),
)

return _asyncify_wrap
9 changes: 3 additions & 6 deletions a_sync/a_sync/function.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ from async_property.base import AsyncPropertyDescriptor # type: ignore [import]
from async_property.cached import AsyncCachedPropertyDescriptor # type: ignore [import]

from a_sync._typing import *
from a_sync.a_sync import _helpers
from a_sync.a_sync cimport _kwargs
from a_sync.a_sync._helpers cimport _asyncify, _await
from a_sync.a_sync.flags import VIABLE_FLAGS
from a_sync.a_sync.modifiers.manager import ModifierManager

Expand Down Expand Up @@ -54,11 +54,9 @@ class _ModifiedMixin:
The asynchronous version of the function with applied modifiers.

See Also:
- :func:`_helpers._asyncify`
- :meth:`ModifierManager.apply_async_modifiers`
"""
coro_fn = _helpers._asyncify(func, self.modifiers.executor)
return self.modifiers.apply_async_modifiers(coro_fn)
return self.modifiers.apply_async_modifiers(_asyncify(func, self.modifiers.executor))

@functools.cached_property
def _await(self) -> Callable[[Awaitable[T]], T]:
Expand All @@ -69,10 +67,9 @@ class _ModifiedMixin:
The modified _await function.

See Also:
- :func:`_helpers._await`
- :meth:`ModifierManager.apply_sync_modifiers`
"""
return self.modifiers.apply_sync_modifiers(_helpers._await)
return self.modifiers.apply_sync_modifiers(_await)

@functools.cached_property
def default(self) -> DefaultMode:
Expand Down
6 changes: 2 additions & 4 deletions a_sync/a_sync/method.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ asynchronously based on various conditions and configurations.
# mypy: disable-error-code=valid-type
# mypy: disable-error-code=misc
import functools
import heapq
import logging
import weakref
from inspect import isawaitable

from a_sync import exceptions
from a_sync._typing import *
from a_sync.a_sync import _helpers
from a_sync.a_sync cimport _kwargs
from a_sync.a_sync._descriptor import ASyncDescriptor
from a_sync.a_sync._helpers cimport _await
from a_sync.a_sync.function import (
ASyncFunction,
ASyncFunctionAsyncDefault,
Expand Down Expand Up @@ -585,7 +583,7 @@ class ASyncBoundMethod(ASyncFunction[P, T], Generic[I, P, T]):
logger.debug(
"awaiting %s for %s args: %s kwargs: %s", coro, self, args, kwargs
)
retval = _helpers._await(coro)
retval = _await(coro)
logger.debug(
"returning %s for %s args: %s kwargs: %s", retval, self, args, kwargs
)
Expand Down
7 changes: 4 additions & 3 deletions a_sync/a_sync/property.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ from typing_extensions import Unpack

from a_sync import _smart
from a_sync._typing import *
from a_sync.a_sync import _helpers, config
from a_sync.a_sync import config
from a_sync.a_sync._helpers cimport _asyncify, _await
from a_sync.a_sync._descriptor import ASyncDescriptor
from a_sync.a_sync.function import (
ASyncFunction,
Expand Down Expand Up @@ -82,7 +83,7 @@ class _ASyncPropertyDescriptorBase(ASyncDescriptor[I, Tuple[()], T]):
if asyncio.iscoroutinefunction(_fget):
self._fget = self.__wrapped__
else:
self._fget = _helpers._asyncify(self.__wrapped__, self.modifiers.executor)
self._fget = _asyncify(self.__wrapped__, self.modifiers.executor)

@overload
def __get__(self, instance: None, owner: Type[I]) -> Self: ...
Expand Down Expand Up @@ -130,7 +131,7 @@ class _ASyncPropertyDescriptorBase(ASyncDescriptor[I, Tuple[()], T]):
instance,
owner,
)
retval = _helpers._await(awaitable)
retval = _await(awaitable)
else:
retval = awaitable

Expand Down
12 changes: 6 additions & 6 deletions a_sync/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,8 @@ class _TaskMappingView(ASyncGenericBase, Iterable[T], Generic[T, K, V]):
_get_from_item: Callable[[Tuple[K, V]], T]
_pop: bool = False

__slots__ = "__view__", "__mapping__"

def __init__(
self, view: Iterable[T], task_mapping: TaskMapping[K, V], pop: bool = False
) -> None:
Expand All @@ -751,16 +753,11 @@ def __iter__(self) -> Iterator[T]:
return iter(self.__view__)

def __await__(self) -> Generator[Any, None, List[T]]:
return self._await().__await__()
return self.__await().__await__()

def __len__(self) -> int:
return len(self.__view__)

async def _await(self) -> List[T]:
return [result async for result in self]

__slots__ = "__view__", "__mapping__"

async def aiterbykeys(self, reverse: bool = False) -> ASyncIterator[T]:
async for tup in ASyncSorter(
self.__mapping__.items(pop=self._pop), key=_get_key, reverse=reverse
Expand All @@ -773,6 +770,9 @@ async def aiterbyvalues(self, reverse: bool = False) -> ASyncIterator[T]:
):
yield self._get_from_item(tup)

async def __await(self) -> List[T]:
return [result async for result in self]


class TaskMappingKeys(_TaskMappingView[K, K, V], Generic[K, V]):
"""
Expand Down

0 comments on commit 2ef1091

Please sign in to comment.