question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add decorator to make plain functions return a Result

See original GitHub issue

Idea

While using the library, I came up with the idea to implement a simple decorator that wraps any plain function into try-except and returns an Err if an exception occurred. This makes it very easy to wrap existing “unsafe” functions and thus prevent runtime errors.

Example:

@safe_wrap
def i_will_fail():
  raise Exception

@safe_wrap
def i_will_succeed():
  return 42

output = i_will_fail()
assert(output.is_err())

output = i_will_succeed()
assert(output.is_ok())

Existing implementation

Just to give you an idea, here is my naive first implementation (shortened):

@singledispatch
def safe_wrap(f: Callable[[Any], Any], O]) -> Callable[[Any, Any], Result[O, Exception]]:
    @wraps(f)
    def wrapper(*args: Any, **kwargs: Any) -> Result[O, Exception]:
        try:
            return Ok(f(args, kwargs))
        except Exception as err:
            return Err(err)
    return wrapper

# and now we register calls with no args and args only and kwargs only
@safe_wrap.register
def _(f: Callable[[Optional[Any]], O]) -> Callable[[Any, Any], Result[O, Exception]]:
[...]

Downsides

Typing arbitrary *args and **kwargs is not trivial, as described in https://github.com/python/mypy/issues/5876. In my current implementation, I work around this with using Any and a generic dispatch. Nevertheless, this may not comply with the excessive typing that the rest of result-module aims for.

Question(s)

What do you think about the concept and do you want something like this in the library? If so, I could provide a PR with a more elaborated version of the code shown above.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:13 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
wbolstercommented, Dec 24, 2021

good news everybody, as_result() is now merged #71

see the readme for example usage!

1reaction
noah04commented, Nov 1, 2021

@wbolster if I remember correctly, I did that to enable generic calls with args and/or kwargs using the same decorator. But don‘t rely on that piece of code - I‘m not that into Python generics/typing.

Mentioning that, I would really like you for investing time on this topic 👍🏼

Read more comments on GitHub >

github_iconTop Results From Across the Web

Primer on Python Decorators
In this introductory tutorial, we'll look at what Python decorators are and how to create and use them.
Read more >
python decorator - is it possible to return a function that ...
e.g: i have a caching decorator that wraps a function with ttl param. @cache(ttl = 10) def test(x) i would like to have...
Read more >
How to Create and Use Decorators in Python With Examples
Python decorators allow you to change the behavior of a function without modifying the function itself. In this article I will show you...
Read more >
Using Function Decorators in Python | by Wei-Meng Lee
In this article, I will talk about function decorators in Python, a topic that is not easy to grasp, but an extremely useful...
Read more >
Improve Your Code with Decorators | Python in Plain English
A decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it. Let's break...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found