Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ _helpers:

- &static_analysis
stage: Static analysis
<<: *python36
<<: *python37
after_success: skip

- &code_style_check
stage: Code style check
<<: *python36
<<: *python37
after_success: skip

script:
Expand Down Expand Up @@ -91,7 +91,6 @@ jobs:
script:
- bandit -r threaded
- <<: *static_analysis
<<: *python37
name: "MyPy"
install:
- *upgrade_python_toolset
Expand Down
2 changes: 1 addition & 1 deletion doc/source/gthreadpooled.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,5 @@ API: Decorators: `GThreadPooled`, `gthreadpooled`.
Post function to gevent.threadpool.ThreadPool.

:param func: function to wrap
:type func: typing.Optional[typing.Callable]
:type func: typing.Optional[typing.Callable[..., typing.Union[typing.Any, typing.Awaitable]]]
:rtype: typing.Union[GThreadPooled, typing.Callable[..., gevent.event.AsyncResult]]
4 changes: 2 additions & 2 deletions doc/source/threaded.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ API: Decorators: `Threaded` class and `threaded` function.
:param name: New thread name.
If callable: use as wrapped function.
If none: use wrapped function name.
:type name: typing.Optional[typing.Union[str, typing.Callable[.., typing.Union[typing.Any, typing.Awaitable]]]]
:type name: typing.Optional[typing.Union[str, typing.Callable[..., typing.Union[typing.Any, typing.Awaitable]]]]
:param daemon: Daemonize thread.
:type daemon: bool
:param started: Return started thread
Expand Down Expand Up @@ -53,7 +53,7 @@ API: Decorators: `Threaded` class and `threaded` function.
:param name: New thread name.
If callable: use as wrapped function.
If none: use wrapped function name.
:type name: typing.Optional[typing.Union[str, typing.Callable]]
:type name: typing.Optional[typing.Union[str, typing.Callable[..., typing.Union[typing.Any, typing.Awaitable]]]]
:param daemon: Daemonize thread.
:type daemon: bool
:param started: Return started thread
Expand Down
27 changes: 11 additions & 16 deletions threaded/_asynciotask.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class AsyncIOTask(_class_decorator.BaseDecorator):

def __init__(
self,
func: typing.Optional[typing.Callable] = None,
func: typing.Optional[typing.Callable[..., 'typing.Awaitable']] = None,
*,
loop_getter: typing.Union[
typing.Callable[..., asyncio.AbstractEventLoop],
Expand All @@ -47,7 +47,7 @@ def __init__(
"""Wrap function in future and return.

:param func: Function to wrap
:type func: typing.Optional[typing.Callable]
:type func: typing.Optional[typing.Callable[..., typing.Awaitable]]
:param loop_getter: Method to get event loop, if wrap in asyncio task
:type loop_getter: typing.Union[
typing.Callable[..., asyncio.AbstractEventLoop],
Expand All @@ -69,10 +69,7 @@ def loop_getter(
]:
"""Loop getter.

:rtype: typing.Union[
typing.Callable[..., asyncio.AbstractEventLoop],
asyncio.AbstractEventLoop
]
:rtype: typing.Union[typing.Callable[..., asyncio.AbstractEventLoop], asyncio.AbstractEventLoop]
"""
return self.__loop_getter

Expand All @@ -98,31 +95,29 @@ def get_loop(

def _get_function_wrapper(
self,
func: typing.Callable
func: typing.Callable[..., 'typing.Awaitable']
) -> typing.Callable[..., asyncio.Task]:
"""Here should be constructed and returned real decorator.

:param func: Wrapped function
:type func: typing.Callable
:type func: typing.Callable[..., typing.Awaitable]
:return: wrapper, which will produce asyncio.Task on call with function called inside it
:rtype: typing.Callable[..., asyncio.Task]
"""
# pylint: disable=missing-docstring
# noinspection PyMissingOrEmptyDocstring
@functools.wraps(func)
@functools.wraps(func) # pylint: disable=missing-docstring
def wrapper(
*args, # type: typing.Any
**kwargs # type: typing.Any
) -> asyncio.Task:
loop = self.get_loop(*args, **kwargs)
return loop.create_task(func(*args, **kwargs))

# pylint: enable=missing-docstring
return wrapper

def __call__( # pylint: disable=useless-super-delegation
self,
*args: typing.Union[typing.Callable, typing.Any],
*args: typing.Union[typing.Callable[..., 'typing.Awaitable'], typing.Any],
**kwargs: typing.Any
) -> typing.Union[asyncio.Task, typing.Callable[..., asyncio.Task]]:
"""Callable instance."""
Expand Down Expand Up @@ -161,7 +156,7 @@ def asynciotask(

@typing.overload # noqa: F811
def asynciotask(
func: typing.Callable,
func: typing.Callable[..., 'typing.Awaitable'],
*,
loop_getter: typing.Union[
typing.Callable[..., asyncio.AbstractEventLoop],
Expand All @@ -175,7 +170,7 @@ def asynciotask(

# pylint: enable=unused-argument
def asynciotask( # noqa: F811
func: typing.Optional[typing.Callable] = None,
func: typing.Optional[typing.Callable[..., 'typing.Awaitable']] = None,
*,
loop_getter: typing.Union[
typing.Callable[..., asyncio.AbstractEventLoop],
Expand All @@ -186,7 +181,7 @@ def asynciotask( # noqa: F811
"""Wrap function in future and return.

:param func: Function to wrap
:type func: typing.Optional[typing.Callable]
:type func: typing.Optional[typing.Callable[..., typing.Awaitable]]
:param loop_getter: Method to get event loop, if wrap in asyncio task
:type loop_getter: typing.Union[
typing.Callable[..., asyncio.AbstractEventLoop],
Expand All @@ -208,4 +203,4 @@ def asynciotask( # noqa: F811
loop_getter=loop_getter,
loop_getter_need_context=loop_getter_need_context
)(func)
# pylint: enable=unexpected-keyword-arg, no-value-for-parameter, function-redefined
# pylint: enable=function-redefined
17 changes: 11 additions & 6 deletions threaded/_class_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,29 +83,32 @@ def __init__(
@property
def _func(
self
) -> typing.Optional[typing.Callable]:
) -> typing.Optional[typing.Callable[..., typing.Union['typing.Awaitable', typing.Any]]]:
"""Get wrapped function.

:rtype: typing.Optional[typing.Callable]
:rtype: typing.Optional[typing.Callable[..., typing.Union[typing.Awaitable, typing.Any]]]
"""
return self.__func # pragma: no cover

@abc.abstractmethod
def _get_function_wrapper(
self,
func: typing.Callable
func: typing.Callable[..., typing.Union['typing.Awaitable', typing.Any]]
) -> typing.Callable:
"""Here should be constructed and returned real decorator.

:param func: Wrapped function
:type func: typing.Callable
:type func: typing.Callable[..., typing.Union[typing.Awaitable, typing.Any]]
:rtype: typing.Callable
"""
raise NotImplementedError() # pragma: no cover

def __call__(
self,
*args: typing.Union[typing.Callable, typing.Any],
*args: typing.Union[
typing.Callable[..., typing.Union['typing.Awaitable', typing.Any]],
typing.Any
],
**kwargs: typing.Any
) -> typing.Any:
"""Main decorator getter."""
Expand All @@ -122,7 +125,9 @@ def __call__(
return wrapper

@staticmethod
def _await_if_required(target: typing.Callable) -> typing.Callable[..., typing.Any]:
def _await_if_required(
target: typing.Callable[..., typing.Union['typing.Awaitable', typing.Any]]
) -> typing.Callable[..., typing.Any]:
"""Await result if coroutine was returned."""
@functools.wraps(target)
def wrapper(
Expand Down
27 changes: 13 additions & 14 deletions threaded/_gthreadpooled.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ class GThreadPooled(_base_threaded.APIPooled):

__executor = None # type: typing.Optional[gevent.threadpool.ThreadPool]

# pylint: disable=arguments-differ
@classmethod
def configure(
def configure( # pylint: disable=arguments-differ
cls: typing.Type['GThreadPooled'],
max_workers: typing.Optional[int] = None,
hub: typing.Optional[gevent.hub.Hub] = None
Expand Down Expand Up @@ -70,8 +69,6 @@ def configure(
hub=hub
)

# pylint: enable=arguments-differ

@classmethod
def shutdown(cls: typing.Type['GThreadPooled']) -> None:
"""Shutdown executor.
Expand All @@ -93,32 +90,33 @@ def executor(self) -> gevent.threadpool.ThreadPool:

def _get_function_wrapper(
self,
func: typing.Callable
func: typing.Callable[..., typing.Union['typing.Awaitable', typing.Any]]
) -> typing.Callable[..., gevent.event.AsyncResult]:
"""Here should be constructed and returned real decorator.

:param func: Wrapped function
:type func: typing.Callable
:type func: typing.Callable[..., typing.Union[typing.Awaitable, typing.Any]
:return: wrapped coroutine or function
:rtype: typing.Callable[..., gevent.event.AsyncResult]
"""
prepared = self._await_if_required(func)

# pylint: disable=missing-docstring
# noinspection PyMissingOrEmptyDocstring
@functools.wraps(prepared)
@functools.wraps(prepared) # pylint: disable=missing-docstring
def wrapper(
*args, # type: typing.Any
**kwargs # type: typing.Any
) -> gevent.event.AsyncResult:
return self.executor.spawn(prepared, *args, **kwargs)

# pylint: enable=missing-docstring
return wrapper

def __call__( # pylint: disable=useless-super-delegation
self,
*args: typing.Union[typing.Callable, typing.Any],
*args: typing.Union[
typing.Callable[..., typing.Union['typing.Awaitable', typing.Any]],
typing.Any
],
**kwargs: typing.Any
) -> typing.Union[gevent.event.AsyncResult, typing.Callable[..., gevent.event.AsyncResult]]:
"""Callable instance."""
Expand All @@ -127,7 +125,9 @@ def __call__( # pylint: disable=useless-super-delegation

# pylint: disable=function-redefined, unused-argument
@typing.overload
def gthreadpooled(func: typing.Callable) -> typing.Callable[..., gevent.event.AsyncResult]:
def gthreadpooled(
func: typing.Callable[..., typing.Union['typing.Awaitable', typing.Any]]
) -> typing.Callable[..., gevent.event.AsyncResult]:
"""Overloaded: func provided."""
pass # pragma: no cover

Expand All @@ -139,9 +139,8 @@ def gthreadpooled(func: None = None) -> GThreadPooled:


# pylint: enable=unused-argument
# pylint: disable=unexpected-keyword-arg, no-value-for-parameter
def gthreadpooled( # noqa: F811
func: typing.Optional[typing.Callable] = None
func: typing.Optional[typing.Callable[..., typing.Union['typing.Awaitable', typing.Any]]] = None
) -> typing.Union[GThreadPooled, typing.Callable[..., gevent.event.AsyncResult]]:
"""Post function to gevent.threadpool.ThreadPool.

Expand All @@ -153,4 +152,4 @@ def gthreadpooled( # noqa: F811
if func is None:
return GThreadPooled(func=func)
return GThreadPooled(func=None)(func)
# pylint: enable=unexpected-keyword-arg, no-value-for-parameter, function-redefined
# pylint: enable=function-redefined
24 changes: 15 additions & 9 deletions threaded/_threaded.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ class Threaded(_class_decorator.BaseDecorator):

def __init__(
self,
name: typing.Optional[typing.Union[str, typing.Callable]] = None,
name: typing.Optional[
typing.Union[
str,
typing.Callable[..., typing.Union['typing.Awaitable', typing.Any]]
]
] = None,
daemon: bool = False,
started: bool = False,
) -> None:
Expand All @@ -49,7 +54,7 @@ def __init__(
:param name: New thread name.
If callable: use as wrapped function.
If none: use wrapped function name.
:type name: typing.Optional[typing.Union[str, typing.Callable]]
:type name: typing.Optional[typing.Union[str, typing.Callable[..., typing.Union[typing.Awaitable, typing.Any]]]]
:param daemon: Daemonize thread.
:type daemon: bool
:param started: Return started thread
Expand Down Expand Up @@ -105,12 +110,12 @@ def __repr__(self) -> str:

def _get_function_wrapper(
self,
func: typing.Callable
func: typing.Callable[..., typing.Union['typing.Awaitable', typing.Any]]
) -> typing.Callable[..., threading.Thread]:
"""Here should be constructed and returned real decorator.

:param func: Wrapped function
:type func: typing.Callable
:type func: typing.Callable[..., typing.Union[typing.Awaitable, typing.Any]]
:return: wrapped function
:rtype: typing.Callable[..., threading.Thread]
"""
Expand All @@ -123,9 +128,8 @@ def _get_function_wrapper(
str(hash(func))
)

# pylint: disable=missing-docstring
# noinspection PyMissingOrEmptyDocstring
@functools.wraps(prepared)
@functools.wraps(prepared) # pylint: disable=missing-docstring
def wrapper(
*args, # type: typing.Any
**kwargs # type: typing.Any
Expand All @@ -141,12 +145,14 @@ def wrapper(
thread.start()
return thread

# pylint: enable=missing-docstring
return wrapper

def __call__( # pylint: disable=useless-super-delegation
self,
*args: typing.Union[typing.Callable, typing.Any],
*args: typing.Union[
typing.Callable[..., typing.Union['typing.Awaitable', typing.Any]],
typing.Any
],
**kwargs: typing.Any
) -> typing.Union[threading.Thread, typing.Callable[..., threading.Thread]]:
"""Executable instance."""
Expand Down Expand Up @@ -200,4 +206,4 @@ def threaded( # noqa: F811
)
return Threaded(name=name, daemon=daemon, started=started)(func) # type: ignore
return Threaded(name=name, daemon=daemon, started=started)
# pylint: enable=unexpected-keyword-arg, no-value-for-parameter, function-redefined
# pylint: enable=function-redefined
Loading