Skip to content

Support for the Michele Simionato's 'decorator' module. #697

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

Closed
pytestbot opened this issue Mar 13, 2015 · 19 comments
Closed

Support for the Michele Simionato's 'decorator' module. #697

pytestbot opened this issue Mar 13, 2015 · 19 comments
Labels
type: enhancement new feature or API change, should be merged into features branch

Comments

@pytestbot
Copy link
Contributor

Originally reported by: Vladislav Turbanov (BitBucket: iptvd, GitHub: iptvd)


I'm getting the following error, while using the Simionato's useful 'decorator' module https://pypi.python.org/pypi/decorator , which helps decorators preseve the original wrapped function signature.

#!bash

INTERNALERROR>   File "P:/msys64/mingw64/lib/python2.7/site-packages/_pytest/runner.py", line 217, in pytest_runtest_makereport
INTERNALERROR>     style=item.config.option.tbstyle)
INTERNALERROR>   File "P:/msys64/mingw64/lib/python2.7/site-packages/_pytest/python.py", line 593, in _repr_failure_py
INTERNALERROR>     style=style)
INTERNALERROR>   File "P:/msys64/mingw64/lib/python2.7/site-packages/_pytest/main.py", line 394, in _repr_failure_py
INTERNALERROR>     return excinfo.value.formatrepr()
INTERNALERROR>   File "P:/msys64/mingw64/lib/python2.7/site-packages/_pytest/python.py", line 1489, in formatrepr
INTERNALERROR>     lines, _ = inspect.getsourcelines(function)
INTERNALERROR>   File "P:/msys64/mingw64/lib/python2.7/inspect.py", line 690, in getsourcelines
INTERNALERROR>     lines, lnum = findsource(object)
INTERNALERROR>   File "P:/msys64/mingw64/lib/python2.7/inspect.py", line 538, in findsource
INTERNALERROR>     raise IOError('could not get source code')
INTERNALERROR> IOError: could not get source code

The solution to the problem is here: http://micheles.googlecode.com/hg/decorator/documentation.html#getting-the-source-code

The decorator's functions have a special member __wrapped__ , which can be used to get the source code. So the following change in the pytest/python.py:1489 file can eliminate the error.

#!python

            try:
                lines, _ = inspect.getsourcelines(function)
            except Exception, e:
                # Try to handle the Michele Simionato's decorator case.
                if hasattr(function, '__wrapped__'):
                    lines, _ = inspect.getsourcelines(function.__wrapped__)
                else:
                    raise e

I've also noticed, that you are already using this techinque in the same python.py file. Maybe, it is the way to get the source lines. Your technique is:

#!python

while hasattr(realfunction, "__wrapped__"):
    realfunction = realfunction.__wrapped__

@pytestbot
Copy link
Contributor Author

Original comment by Éric Araujo (BitBucket: Merwok, GitHub: Merwok):


Note that recent Python stdlibs also set __wrapped__ (e.g. in functools.wraps), so this would be useful for more than just code using this decorator lib.

@pytestbot
Copy link
Contributor Author

Original comment by Bruno Oliveira (BitBucket: nicoddemus, GitHub: nicoddemus):


Thanks, you seem to have got to the bottom of the issue... Can you go ahead and provide a PR? I think the while hasattr(...) technique is the better approach.

@pytestbot
Copy link
Contributor Author

Original comment by Éric Araujo (BitBucket: Merwok, GitHub: Merwok):


Python 3.4 provides inspect.unwrap for this use case; it’s a little more complicated than the hasattr solution. Code is here, for inspiration if not for copying depending on licensing compatibility:

https://hg.python.org/cpython/rev/2aa6c1e35b8a

http://bugs.python.org/issue13266

@pytestbot
Copy link
Contributor Author

Original comment by Bruno Oliveira (BitBucket: nicoddemus, GitHub: nicoddemus):


I see, thanks for the links!

I think a solution would be to use inspect.unwrap when available, and fallback to the while hasattr(...) technique (as it seems to fit pytest's needs):

if hasattr(inspect, 'unwrap'):
    realfunction = inspect.unwrap(realfunction)
else:
    while hasattr(realfunction, "__wrapped__"):
        realfunction = realfunction.__wrapped__

@pytestbot
Copy link
Contributor Author

Original comment by Éric Araujo (BitBucket: Merwok, GitHub: Merwok):


Sounds good.

@pytestbot
Copy link
Contributor Author

Original comment by Vladislav Turbanov (BitBucket: iptvd, GitHub: iptvd):


Didn't dig into the unwrap thingy, but looks sane. Should other code use the unwrap techique then? Maybe we have to introduce a common method - resolve for the functions to get their real counterparts, what do you think? Myself don't have time for a PR right now...

@pytestbot
Copy link
Contributor Author

Original comment by Bruno Oliveira (BitBucket: nicoddemus, GitHub: nicoddemus):


Yes, the appropriate approach would be to implement something like:

def unwrap_func(func):
    if hasattr(inspect, 'unwrap'):
        return inspect.unwrap(func)
    else:
        while hasattr(func, "__wrapped__"):
            func = func.__wrapped__
        return func

And apply this in other parts of the code base that need something similar... probably everywhere that uses inspect.getsource and possibly other inspect functions as well.

Anyone volunteers to write a PR? :)

@pytestbot
Copy link
Contributor Author

Original comment by Vladislav Turbanov (BitBucket: iptvd, GitHub: iptvd):


Not-Me-penguins-of-madagascar-18270082-470-349.jpg

pardon me, please!

@pytestbot
Copy link
Contributor Author

Original comment by Bruno Oliveira (BitBucket: nicoddemus, GitHub: nicoddemus):


I approve the reference, for obvious reasons. :)

@pytestbot
Copy link
Contributor Author

Original comment by holger krekel (BitBucket: hpk42, GitHub: hpk42):


some function like "py.code.unwrap_function" and maybe "py.code.getsource" could be a good place -- it can be accessed from anywhere in pytest and py. I am also fine with a location in _pytest/python.py or so.

@pytestbot pytestbot added the type: enhancement new feature or API change, should be merged into features branch label Jun 15, 2015
@RonnyPfannschmidt
Copy link
Member

we recently addded wrapper inwrapping, is this still an issue @nicoddemus @vladipus

@nicoddemus
Copy link
Member

@RonnyPfannschmidt

wrapper inwrapping

What do you mean?

@RonnyPfannschmidt
Copy link
Member

whops, typo, i meant unwrapping, py.test now iterates until it no longer finds a wrapped attribute

@RonnyPfannschmidt
Copy link
Member

@nicoddemus ping?

@nicoddemus
Copy link
Member

@vladipus can you confirm this is still an issue?

@RonnyPfannschmidt
Copy link
Member

closing due to lack of feedback, please reopen/notify

@sharad1087
Copy link

I think this is still an issue.
I am unable to use @responses.activate with pytest.

@The-Compiler
Copy link
Member

@sharad1087 And what exactly happens when you do?

FWIW responses seems to have some code trying to keep compatibility with pytest and other things inspecting the signature of something.

@sharad1087
Copy link

My requests was neither served by the (mock) response I added nor was actually attempting to reach the server. It simply said 'Connection Refused'.

I'll try few more things and refer the attached code (thanks for pointing to it!) and share any updates I have.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement new feature or API change, should be merged into features branch
Projects
None yet
Development

No branches or pull requests

5 participants