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

assert_trace does not work correctly with functions that use the same decorator #876

Open
thepabloaguilar opened this issue Mar 27, 2021 · 6 comments
Labels
bug Something isn't working

Comments

@thepabloaguilar
Copy link
Member

Bug report

What's wrong

Our assert_trace from pytest plugin doesn't work correctly when two or more different functions are using the same decorator, it not considers that those functions are different! See the example below:

def test_two_functios_using_same_decorator(returns: ReturnsAsserts):
    def decorator(func):
        def decorated(*args, **kwargs):
            return func(*args, **kwargs)
        return decorated

    @decorator
    def func_one():
        return Success(42)

    @decorator
    def func_two():
        return Success(42)

    with returns.assert_trace(Success, func_one):
        func_two()

That test should fail because we want to assert the Success creation inside func_one, but I'm calling func_two and the test is passing!

How is that should be

Our pytest plugin should consider that those functions are different!

System information

  • python version: 3.9
  • returns version: 0.16.0
@thepabloaguilar thepabloaguilar added the bug Something isn't working label Mar 27, 2021
@sobolevn
Copy link
Member

sobolevn commented Mar 27, 2021

What if we use @wraps on def decorated? 🤔

@thepabloaguilar
Copy link
Member Author

Also doesn't work, I tested with safe too (safe uses wraps)
wraps just keep some metadata like name and docstring. But if we get the code from them they are the same

@thepabloaguilar
Copy link
Member Author

I know how to solve this issue! Reading the Python docs I discovered that wrapped functions has the __wrapped__ attribute which we can use to get the "original" function!

The users just need to pay attention to use the wraps decorator inside their decorators!

Docs: https://docs.python.org/3/library/functools.html#functools.update_wrapper

@sobolevn
Copy link
Member

sobolevn commented Nov 3, 2022

Let's add this to the docs :)

@thepabloaguilar
Copy link
Member Author

I made the fix and broke other part 😆

The thing is, fixing this (with the actual code ive made) we won't be able to handle creations within decorators cause we're getting the most inner function, @safe won't work for example:

@safe
def _safe_decorated_function(return_failure: bool = False):
    if return_failure:
        raise ValueError('Function failed')

def test_something():
    with returns.assert_trace(container_type, _safe_decorated_function):
        _safe_decorated_function(True)

Failure is being created inside safe and not _safe_decorated_function

Suggestions?

@sobolevn
Copy link
Member

Suggestions?

No :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

No branches or pull requests

2 participants