Skip to content

Commit

Permalink
feat: check that async_early_return is applied on async functions (#79)
Browse files Browse the repository at this point in the history
* feat: check that async_early_return is applied on async functions

* chore: ignore lint error

* chore: reorder checks
  • Loading branch information
fgsalomon authored Oct 21, 2024
1 parent 842890d commit 1fca6c6
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 6 deletions.
6 changes: 6 additions & 0 deletions meiga/decorators/async_decoration_error.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from meiga.error import Error


class AsyncDecorationError(Error):
def __init__(self) -> None:
self.message = "meiga async decorators must be declared on async functions"
5 changes: 5 additions & 0 deletions meiga/decorators/async_early_return.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import inspect
import sys
from functools import wraps
from typing import Any, Callable, Coroutine, TypeVar, cast

from meiga.decorators.async_decoration_error import AsyncDecorationError

if sys.version_info < (3, 10): # pragma: no cover
from typing_extensions import ParamSpec
else:
Expand Down Expand Up @@ -29,6 +32,8 @@ async def _async_early_return(*args: P.args, **kwargs: P.kwargs) -> R:
return Failure(UnexpectedDecorationOrderError()) # type: ignore
elif isinstance(func, classmethod):
return Failure(UnexpectedDecorationOrderError()) # type: ignore
elif not inspect.iscoroutinefunction(func):
return Failure(AsyncDecorationError()) # type: ignore
else:
return await func(*args, **kwargs)
except WaitingForEarlyReturn as exc:
Expand Down
6 changes: 4 additions & 2 deletions meiga/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ def execute(self, result: Result[TS, TF]) -> None:
self.func(result.value)


class OnSuccessHandler(Handler): ...
class OnSuccessHandler(Handler):
...


class OnFailureHandler(Handler): ...
class OnFailureHandler(Handler):
...
6 changes: 4 additions & 2 deletions tests/unit/doc/example_with_meiga.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
from meiga import Error, Failure, Result, Success


class NoSuchKey(Error): ...
class NoSuchKey(Error):
...


class TypeMismatch(Error): ...
class TypeMismatch(Error):
...


def string_from_key(dictionary: dict, key: str) -> Result[str, NoSuchKey | TypeMismatch]:
Expand Down
6 changes: 4 additions & 2 deletions tests/unit/doc/example_without_meiga.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
class NoSuchKey(Exception): ...
class NoSuchKey(Exception):
...


class TypeMismatch(Exception): ...
class TypeMismatch(Exception):
...


# This return value masks the behavior of the unhappy path (Exceptions). 🥲
Expand Down
13 changes: 13 additions & 0 deletions tests/unit/test_async_early_return.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from meiga import BoolResult, Error, async_early_return, isFailure, isSuccess
from meiga.assertions import assert_failure, assert_success
from meiga.decorators import UnexpectedDecorationOrderError
from meiga.decorators.async_decoration_error import AsyncDecorationError


@pytest.mark.unit
Expand Down Expand Up @@ -107,3 +108,15 @@ async def decorated_method(cls) -> BoolResult:
result = await MyClass.decorated_method()
assert_failure(result, value_is_instance_of=UnexpectedDecorationOrderError)
assert result.value.message == "meiga decorators must be declared after a @staticmethod, @classmethod"

async def should_return_an_async_decorator_failure_result_with_async_early_return_on_normal_function(
self,
):
class MyClass:
@async_early_return
def decorated_method(cls) -> BoolResult:
return isSuccess

result = await MyClass.decorated_method()
assert_failure(result, value_is_instance_of=AsyncDecorationError)
assert result.value.message == "meiga async decorators must be declared on async functions"

0 comments on commit 1fca6c6

Please sign in to comment.