Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature black linting #8

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
30 changes: 14 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# mediatr_py

[![PyPI](https://img.shields.io/pypi/v/mediatr)](https://pypi.org/project/mediatr)
[![Python](https://img.shields.io/pypi/pyversions/mediatr)](https://pypi.org/project/mediatr)
[![Downloads](https://img.shields.io/pypi/dm/mediatr)](https://pypi.org/project/mediatr)
[![Python](https://img.shields.io/pypi/pyversions/mediatr)](https://pypi.org/project/mediatr)
[![Downloads](https://img.shields.io/pypi/dm/mediatr)](https://pypi.org/project/mediatr)

<a href="https://www.buymeacoffee.com/megafetis" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

Expand All @@ -11,7 +11,8 @@ This is an async implementation of Mediator pattern with pipline behaviors.
It is a port of [Mediatr](https://github.com/jbogard/MediatR) from .Net C#

Requirements:
* Python >= 3.6

- Python >= 3.6

## Usage:

Expand All @@ -32,17 +33,17 @@ class GetArrayQuery():
### Define your handler class or function

```py
import Mediator from mediatr
from mediatr import Mediator

@Mediator.handler
async def get_array_handler(request:GetArrayQuery):
items = list()
for i in range(0, request.items_count):
items.append(i)
return items

# or just Mediator.register_handler(get_array_handler)

```

or class:
Expand All @@ -55,14 +56,14 @@ class GetArrayQueryHandler():
for i in range(0, request.items_count):
items.append(i)
return items

# or just Mediator.register_handler(GetArrayQueryHandler)
```

### Run mediator

```py
import Mediator from mediatr
from mediatr import Mediator

mediator = Mediator()

Expand All @@ -80,11 +81,10 @@ print(result) // [0,1,2,3,4]
>
> In another case use `asyncio` module for manual manage of event loop in synchronous code


### Run mediator statically, without instance

```py
import Mediator from mediatr
from mediatr import Mediator

request = GetArrayQuery(5)

Expand All @@ -97,10 +97,10 @@ print(result) // [0,1,2,3,4]
```

Note that instantiation of `Mediator(handler_class_manager = my_manager_func)` is useful if you have custom handlers creation. For example using an injector.
By default class handlers are instantiated with simple init: `SomeRequestHandler()`. handlers or behaviors as functions are executed directly.

By default class handlers are instantiated with simple init: `SomeRequestHandler()`. handlers or behaviors as functions are executed directly.

## Using behaviors

You can define behavior class with method 'handle' or function:

```py
Expand Down Expand Up @@ -137,12 +137,11 @@ def default_handler_class_manager(HandlerCls:type,is_behavior:bool=False):

```


For example, if you want to instantiate them with dependency injector or custom, pass your own factory function to Mediator:

```py
def my_class_handler_manager(handler_class, is_behavior=False):

if is_behavior:
# custom logic
pass
Expand All @@ -152,12 +151,11 @@ def my_class_handler_manager(handler_class, is_behavior=False):
mediator = Mediator(handler_class_manager=my_class_handler_manager)

```
PS:

PS:

The `next` function in behavior is `async`, so if you want to take results or if your behavior is async, use `middle_results = await next()`


Handler may be async too, if you need.

## Using with generic typing support (version >= 1.2):
Expand Down
10 changes: 5 additions & 5 deletions mediatr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
__behaviors__,
GenericQuery,
extract_request_type,
find_behaviors
)
find_behaviors,
)
from .exceptions import (
HandlerNotFoundError,
InvalidRequest,
InvalidHandlerError,
InvalidBehaviorError
InvalidBehaviorError,
)

from ._version import __version__
Expand All @@ -26,5 +26,5 @@
"HandlerNotFoundError",
"InvalidRequest",
"InvalidHandlerError",
"InvalidBehaviorError"
]
"InvalidBehaviorError",
]
2 changes: 1 addition & 1 deletion mediatr/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.3.2'
__version__ = "1.3.2"
26 changes: 19 additions & 7 deletions mediatr/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import inspect


def raise_if_handler_not_found(handler,request):
def raise_if_handler_not_found(handler, request):
if not handler:
raise HandlerNotFoundError(request)

Expand All @@ -18,7 +18,7 @@ def raise_if_handler_is_invalid(handler):
if isfunc:
func = handler
else:
if hasattr(handler, 'handle'):
if hasattr(handler, "handle"):
if inspect.isfunction(handler.handle):
func = handler.handle
elif inspect.ismethod(handler.handle):
Expand All @@ -34,7 +34,11 @@ def raise_if_handler_is_invalid(handler):

def raise_if_behavior_is_invalid(behavior):
isfunc = inspect.isfunction(behavior)
func = behavior if isfunc else (behavior.handle if hasattr(behavior, 'handle') else None)
func = (
behavior
if isfunc
else (behavior.handle if hasattr(behavior, "handle") else None)
)
if not func or not inspect.isfunction(func):
raise InvalidHandlerError(func)
sign = inspect.signature(func)
Expand All @@ -57,14 +61,22 @@ def __init__(self):
class InvalidHandlerError(Exception):
def __init__(self, handler):
self.handler = handler
super().__init__("Incorrect handler: '{}'. Handler must be a class, that contains 'handle' method with args:(self,request:SomeRequestType) \
super().__init__(
"Incorrect handler: '{}'. Handler must be a class, that contains 'handle' method with args:(self,request:SomeRequestType) \
or must be a function with args:(request:SomeRequestType) \
where 'request' is object of request class. See examples on git".format(handler))
where 'request' is object of request class. See examples on git".format(
handler
)
)


class InvalidBehaviorError(Exception):
def __init__(self, behavior):
self.behavior = behavior
super().__init__("Incorrect behavior: '{}'. Behavior must be a class, that contains 'handle' method with args:(self,request:SomeRequestTypeOrObject,next) \
super().__init__(
"Incorrect behavior: '{}'. Behavior must be a class, that contains 'handle' method with args:(self,request:SomeRequestTypeOrObject,next) \
or must be a function with args:(request:SomeRequestTypeOrObject,next) \
where 'next' is coroutine function. See examples on git".format(behavior))
where 'next' is coroutine function. See examples on git".format(
behavior
)
)
81 changes: 49 additions & 32 deletions mediatr/mediator.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
import inspect
from typing import Any, Awaitable, Callable, Optional, TypeVar, Generic, Union

from mediatr.exceptions import raise_if_behavior_is_invalid, raise_if_handler_is_invalid, raise_if_handler_not_found, \
raise_if_request_none
from mediatr.exceptions import (
raise_if_behavior_is_invalid,
raise_if_handler_is_invalid,
raise_if_handler_not_found,
raise_if_request_none,
)

__handlers__ = {}
__behaviors__ = {}
TResponse = TypeVar('TResponse')
TResponse = TypeVar("TResponse")


class GenericQuery(Generic[TResponse]):
pass


@staticmethod
def default_handler_class_manager(HandlerCls:type,is_behavior:bool=False):
def default_handler_class_manager(HandlerCls: type, is_behavior: bool = False):
return HandlerCls()


def extract_request_type(handler, is_behavior=False) -> type:
isfunc = inspect.isfunction(handler)

func = None
if isfunc:
func = handler
else:
if hasattr(handler, 'handle'):
if hasattr(handler, "handle"):
if inspect.isfunction(handler.handle):
func = handler.handle
elif inspect.ismethod(handler.handle):
Expand All @@ -34,11 +42,19 @@ def extract_request_type(handler, is_behavior=False) -> type:

sign = inspect.signature(func)
items = list(sign.parameters)
return sign.parameters.get(items[0]).annotation if isfunc else sign.parameters.get(items[1]).annotation
return (
sign.parameters.get(items[0]).annotation
if isfunc
else sign.parameters.get(items[1]).annotation
)


async def __return_await__(result):
return await result if inspect.isawaitable(result) or inspect.iscoroutine(result) else result
return (
await result
if inspect.isawaitable(result) or inspect.iscoroutine(result)
else result
)


def find_behaviors(request):
Expand All @@ -50,16 +66,19 @@ def find_behaviors(request):
return behaviors


class Mediator():
class Mediator:
"""Class of mediator as entry point to send requests and get responses"""

handler_class_manager = default_handler_class_manager

def __init__(self, handler_class_manager: Callable = None):
if handler_class_manager:
self.handler_class_manager = handler_class_manager

async def send_async(self: Union["Mediator",GenericQuery[TResponse]], request: Optional[GenericQuery[TResponse]] = None) -> Awaitable[TResponse]:
async def send_async(
self: Union["Mediator", GenericQuery[TResponse]],
request: Optional[GenericQuery[TResponse]] = None,
) -> Awaitable[TResponse]:
"""
Send request in async mode and getting response

Expand All @@ -79,8 +98,8 @@ async def send_async(self: Union["Mediator",GenericQuery[TResponse]], request: O
if __handlers__.get(request.__class__):
handler = __handlers__[request.__class__]
elif __handlers__.get(request.__class__.__name__):
handler =__handlers__[request.__class__.__name__]
raise_if_handler_not_found(handler,request)
handler = __handlers__[request.__class__.__name__]
raise_if_handler_not_found(handler, request)
handler_func = None
handler_obj = None
if inspect.isfunction(handler):
Expand All @@ -90,34 +109,36 @@ async def send_async(self: Union["Mediator",GenericQuery[TResponse]], request: O
handler_func = handler_obj.handle
behaviors = find_behaviors(request)

behaviors.append(lambda r,next: handler_func(r))
behaviors.append(lambda r, next: handler_func(r))

async def start_func(i:int):
async def start_func(i: int):
beh = behaviors[i]
beh_func = None
if inspect.isfunction(beh):
beh_func = beh
else:
beh_obj = self1.handler_class_manager(beh, True)
beh_func = beh_obj.handle
return await __return_await__(beh_func(request,lambda: start_func(i+1)))

return await start_func(0)
return await __return_await__(beh_func(request, lambda: start_func(i + 1)))

return await start_func(0)

def send(self: Union["Mediator", GenericQuery[TResponse]], request: Optional[GenericQuery[TResponse]] = None) -> TResponse:
def send(
self: Union["Mediator", GenericQuery[TResponse]],
request: Optional[GenericQuery[TResponse]] = None,
) -> TResponse:
"""
Send request in synchronous mode and getting response

Args:
request (`object`): object of request class

Returns:

response object or `None`

"""

self1 = Mediator if not request else self
request = request or self

Expand All @@ -126,8 +147,8 @@ def send(self: Union["Mediator", GenericQuery[TResponse]], request: Optional[Gen
if __handlers__.get(request.__class__):
handler = __handlers__[request.__class__]
elif __handlers__.get(request.__class__.__name__):
handler =__handlers__[request.__class__.__name__]
raise_if_handler_not_found(handler,request)
handler = __handlers__[request.__class__.__name__]
raise_if_handler_not_found(handler, request)
handler_func = None
handler_obj = None
if inspect.isfunction(handler):
Expand All @@ -136,19 +157,19 @@ def send(self: Union["Mediator", GenericQuery[TResponse]], request: Optional[Gen
handler_obj = self1.handler_class_manager(handler)
handler_func = handler_obj.handle
behaviors = find_behaviors(request)
behaviors.append(lambda r,next: handler_func(r))
behaviors.append(lambda r, next: handler_func(r))

def start_func(i:int):
def start_func(i: int):
beh = behaviors[i]
beh_func = None
if inspect.isfunction(beh):
beh_func = beh
else:
beh_obj = self1.handler_class_manager(beh, True)
beh_func = beh_obj.handle
return beh_func(request,lambda: start_func(i+1))
return beh_func(request, lambda: start_func(i + 1))

return start_func(0)


@staticmethod
def register_handler(handler):
Expand Down Expand Up @@ -177,7 +198,3 @@ def behavior(behavior):
"""Append behavior function or class to global behaviors dictionary"""
Mediator.register_behavior(behavior)
return behavior




2 changes: 1 addition & 1 deletion run.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from mediatr import Mediator
from mediatr import Mediator
Loading