-
Notifications
You must be signed in to change notification settings - Fork 1
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
chore: improve error output when call unwrap_or_return on a function … #80
base: main
Are you sure you want to change the base?
chore: improve error output when call unwrap_or_return on a function … #80
Conversation
…withou @early_return or @async_early_return decorators
@@ -3,12 +3,10 @@ | |||
from meiga import Error, Failure, Result, Success | |||
|
|||
|
|||
class NoSuchKey(Error): | |||
... | |||
class NoSuchKey(Error): ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this depends on some ruff configuration. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New versions of ruff handle things differently to older versions.
@@ -14,6 +14,7 @@ def expected_error(value: str, called_from: Union[str, None] = None, escape: boo | |||
f"This exception wraps the following result -> Result[status: failure | value: {value}]" | |||
f"\nIf you want to handle this error and return a Failure, please use early_return decorator on your function{called_from}." | |||
f"\nMore info about how to use unwrap_or_return in combination with @early_return decorator on https://alice-biometrics.github.io/meiga/usage/result/#unwrap_or_return" | |||
f"\nUse @async_early_return if your are calling from an async function." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried to guess if caller is a regular function or an async one with something like the following:
import inspect
from typing import Union
class WaitingForEarlyReturn(Exception):
result: 'AnyResult' # Replace with the actual class/type if AnyResult is not defined
called_from: Union[str, None]
called_from_coroutine: bool = False
def __init__(self, result: 'AnyResult') -> None:
self.result = result
try:
# Get the stack frame
stack = inspect.stack()[2]
frame = stack.frame
function_name = frame.f_code.co_name # Get the name of the function
filename = stack.filename.split("/")[-1]
# We can't retrieve the actual function object, so we check by name
self.called_from_coroutine = frame.f_globals.get(function_name) and inspect.iscoroutinefunction(frame.f_globals[function_name])
# Create a descriptive string for where this was called from
if self.called_from_coroutine:
self.called_from = f"{function_name} (async) on {filename}"
else:
self.called_from = f"{function_name} on {filename}"
except Exception: # noqa
self.called_from = None
# Call the base class initializer
Exception.__init__(self)
But, I think is not possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know why you say it doesn't work 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because frame.frame.f_globals.get(func)
is alway None, so called_from_coroutine
is always False
.
This is because func
is a string not an actual Callable
.
If you modify the test, you'll notice the code never pass through called_from_coroutine
positive if:
@pytest.mark.asyncio
async def should_log_hint_when_called_async_from_class_function_and_not_early_return(self):
class MyClass:
async def execute(self) -> AnyResult:
result = Failure(Error())
result.unwrap_or_return()
return isSuccess
with pytest.raises(
WaitingForEarlyReturn,
match=expected_error(
"Error",
called_from="execute (async) on test_waiting_for_early_return.py", # <-------- THIS
escape=True,
),
):
await MyClass().execute()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I found a way (not very elegant). Check my last commit
Add missing Pytest asyncio mark
…withou @early_return or @async_early_return decorators