pytest-dev / pytest

The pytest framework makes it easy to write small tests, yet scales to support complex functional testing
https://pytest.org
MIT License
12.08k stars 2.68k forks source link

IndexError in source display #560

Closed pytestbot closed 9 years ago

pytestbot commented 10 years ago

Originally reported by: Thomas Tanner (BitBucket: ttanner, GitHub: ttanner)


Tested with both version 2.6.0 and 2.6.1. Both fail:

$ py.test test.py
===================================================== test session starts ======================================================
platform darwin -- Python 2.7.8 -- py-1.4.22 -- pytest-2.6.1
plugins: bdd, pep8, cache, django, cov, xdist
collected 86 items

test.py EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE..................FF..................FF.....
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/main.py", line 84, in wrap_session
INTERNALERROR>     doit(config, session)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/main.py", line 122, in _main
INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/core.py", line 413, in __call__
INTERNALERROR>     return self._docall(methods, kwargs)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/core.py", line 424, in _docall
INTERNALERROR>     res = mc.execute()
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/core.py", line 315, in execute
INTERNALERROR>     res = method(**kwargs)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/main.py", line 142, in pytest_runtestloop
INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/core.py", line 413, in __call__
INTERNALERROR>     return self._docall(methods, kwargs)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/core.py", line 424, in _docall
INTERNALERROR>     res = mc.execute()
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/core.py", line 315, in execute
INTERNALERROR>     res = method(**kwargs)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/runner.py", line 65, in pytest_runtest_protocol
INTERNALERROR>     runtestprotocol(item, nextitem=nextitem)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/runner.py", line 75, in runtestprotocol
INTERNALERROR>     reports.append(call_and_report(item, "call", log))
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/runner.py", line 111, in call_and_report
INTERNALERROR>     report = hook.pytest_runtest_makereport(item=item, call=call)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/main.py", line 166, in call_matching_hooks
INTERNALERROR>     return hookmethod.pcall(plugins, **kwargs)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/core.py", line 417, in pcall
INTERNALERROR>     return self._docall(methods, kwargs)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/core.py", line 424, in _docall
INTERNALERROR>     res = mc.execute()
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/core.py", line 315, in execute
INTERNALERROR>     res = method(**kwargs)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/runner.py", line 214, in pytest_runtest_makereport
INTERNALERROR>     longrepr = item.repr_failure(excinfo)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/python.py", line 600, in repr_failure
INTERNALERROR>     return self._repr_failure_py(excinfo, style=style)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/python.py", line 593, in _repr_failure_py
INTERNALERROR>     style=style)
INTERNALERROR>   File "<path>/pytest-2.6.1-py2.7.egg/_pytest/main.py", line 411, in _repr_failure_py
INTERNALERROR>     style=style, tbfilter=tbfilter)
INTERNALERROR>   File "<path>/py/_code/code.py", line 412, in getrepr
INTERNALERROR>     return fmt.repr_excinfo(self)
INTERNALERROR>   File "<path>/py/_code/code.py", line 589, in repr_excinfo
INTERNALERROR>     reprtraceback = self.repr_traceback(excinfo)
INTERNALERROR>   File "<path>/py/_code/code.py", line 581, in repr_traceback
INTERNALERROR>     reprentry = self.repr_traceback_entry(entry, einfo)
INTERNALERROR>   File "<path>/py/_code/code.py", line 543, in repr_traceback_entry
INTERNALERROR>     s = self.get_source(source, line_index, excinfo, short=short)
INTERNALERROR>   File "<path>/py/_code/code.py", line 484, in get_source
INTERNALERROR>     lines.append(self.flow_marker + "   " + source.lines[line_index])
INTERNALERROR> IndexError: list index out of range

======================================== 4 failed, 41 passed, 38 error in 1.11 seconds

pytestbot commented 10 years ago

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


And this works with 2.5.2?

pytestbot commented 10 years ago

Original comment by Thomas Tanner (BitBucket: ttanner, GitHub: ttanner):


with 2.5.2 py.test simply quits before running the last test and prints no further messages.

pytestbot commented 10 years ago

Original comment by Thomas Tanner (BitBucket: ttanner, GitHub: ttanner):


There seems to be a one-off error in code.py:repr_traceback_entry()

pytestbot commented 10 years ago

Original comment by Thomas Tanner (BitBucket: ttanner, GitHub: ttanner):


I've tracked it down to code.py: getsource()

A line break in the test function makes the difference. This fails:

#!python
if cond: obj.method(arg)
else: obj.method()

while this works:

#!python
if cond: obj.method(arg)
else:
   obj.method()

Somehow the function source code is not properly parsed in getsource()

pytestbot commented 10 years ago

Original comment by Thomas Tanner (BitBucket: ttanner, GitHub: ttanner):


This simple test reproduces the bug (I can't believe it!)

#!python
def test():
    if False: pass
    else: assert False
pytestbot commented 10 years ago

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


Thanks, Thomas, for the cut-down example! I think Floris (@flub) is going to look into it over the weekend.

pytestbot commented 10 years ago

Original comment by Floris Bruynooghe (BitBucket: flub, GitHub: flub):


Finally traced this down, if you're in a hurry this is the fix: https://bitbucket.org/flub/py/commits/e5a98a808315979d034a299066f41adbf6ac4052

pytestbot commented 10 years ago

Original comment by Floris Bruynooghe (BitBucket: flub, GitHub: flub):


Which you can also install using pip install --pre -i https://devpi.net/flub/dev py

pytestbot commented 10 years ago

Original comment by Thomas Tanner (BitBucket: ttanner, GitHub: ttanner):


Yes, the fix works. thank you!

pytestbot commented 10 years ago

Original comment by Thomas Tanner (BitBucket: ttanner, GitHub: ttanner):


fixed

pytestbot commented 10 years ago

Original comment by Floris Bruynooghe (BitBucket: flub, GitHub: flub):


I'd rather keep this open until in's merged in @hpk42's repo

pytestbot commented 10 years ago

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


Depend on newer version of py

This fixes issue560, a test for which is included here as well.