Skip to content

Make code.FormattedExcinfo.get_source more defensive #8227

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

Merged
merged 2 commits into from
Apr 25, 2021

Conversation

encukou
Copy link
Contributor

@encukou encukou commented Jan 6, 2021

I am trying to investigate a bug in Setuptools, and I ran into this internal error in pytest:

INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/_code/code.py", line 798, in repr_traceback_entry
INTERNALERROR>     s = self.get_source(source, line_index, excinfo, short=short)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/_code/code.py", line 727, in get_source
INTERNALERROR>     lines.append(space_prefix + source.lines[line_index].strip())
INTERNALERROR> IndexError: list index out of range
Full traceback...
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/main.py", line 269, in wrap_session
INTERNALERROR>     session.exitstatus = doit(config, session) or 0
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/main.py", line 323, in _main
INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/hooks.py", line 286, in __call__
INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/manager.py", line 93, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/manager.py", line 84, in <lambda>
INTERNALERROR>     self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/callers.py", line 208, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/callers.py", line 80, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/callers.py", line 187, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/main.py", line 348, in pytest_runtestloop
INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/hooks.py", line 286, in __call__
INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/manager.py", line 93, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/manager.py", line 84, in <lambda>
INTERNALERROR>     self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/callers.py", line 208, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/callers.py", line 80, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/callers.py", line 187, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/runner.py", line 109, in pytest_runtest_protocol
INTERNALERROR>     runtestprotocol(item, nextitem=nextitem)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/runner.py", line 126, in runtestprotocol
INTERNALERROR>     reports.append(call_and_report(item, "call", log))
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/runner.py", line 217, in call_and_report
INTERNALERROR>     report: TestReport = hook.pytest_runtest_makereport(item=item, call=call)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/hooks.py", line 286, in __call__
INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/manager.py", line 93, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/manager.py", line 84, in <lambda>
INTERNALERROR>     self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/callers.py", line 203, in _multicall
INTERNALERROR>     gen.send(outcome)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/skipping.py", line 272, in pytest_runtest_makereport
INTERNALERROR>     rep = outcome.get_result()
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/callers.py", line 80, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/pluggy/callers.py", line 187, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/runner.py", line 337, in pytest_runtest_makereport
INTERNALERROR>     return TestReport.from_item_and_call(item, call)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/reports.py", line 322, in from_item_and_call
INTERNALERROR>     longrepr = item.repr_failure(excinfo)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/python.py", line 1677, in repr_failure
INTERNALERROR>     return self._repr_failure_py(excinfo, style=style)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/nodes.py", line 398, in _repr_failure_py
INTERNALERROR>     return excinfo.getrepr(
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/_code/code.py", line 648, in getrepr
INTERNALERROR>     return fmt.repr_excinfo(self)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/_code/code.py", line 905, in repr_excinfo
INTERNALERROR>     reprtraceback = self.repr_traceback(excinfo_)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/_code/code.py", line 846, in repr_traceback
INTERNALERROR>     reprentry = self.repr_traceback_entry(entry, einfo)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/_code/code.py", line 798, in repr_traceback_entry
INTERNALERROR>     s = self.get_source(source, line_index, excinfo, short=short)
INTERNALERROR>   File "/home/pviktori/dev/setuptools/.tox/py310/lib/python3.10/site-packages/_pytest/_code/code.py", line 727, in get_source
INTERNALERROR>     lines.append(space_prefix + source.lines[line_index].strip())
INTERNALERROR> IndexError: list index out of range

When line_index was a large negative number, get_source failed on source.lines[line_index].
I don't (yet) understand the underlying error (Setuptools does some creative backwards-compatibility stunts with the import machinery), but the pytest code looks like it wants to be defensive here. Possibly, using the same dummy Source as with a large positive line_index is correct.

Sorry for not including tests; I don't know how to test it properly. This is more of a bug report with attached code than a proper pull request :)
It seems related to #752 (but the pylib link there is dead).

When line_index was a large negative number, get_source failed
on `source.lines[line_index]`.
Use the same dummy Source as with a large positive line_index.
@@ -721,11 +721,11 @@ def get_source(
) -> List[str]:
"""Return formatted and marked up source lines."""
lines = []
if source is None or line_index >= len(source.lines):
if source is not None and line_index < 0:
line_index += len(source.lines)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is insufficient still -- for example if len(source.lines) is 4 and line_index is -900 -- you could use % but it would probably be a good idea to figure out why these are negative at all (or refuse to produce source when the number is negative)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's why there's line_index < 0 in the next condition :)
I'll try to investigate why this happens in the setuptools tests.

@domdfcoding
Copy link
Contributor

domdfcoding commented Mar 22, 2021

I have encountered the same error on Python 3.10, with a test using the ast module.

I can induce the crash with:

import ast
import pytest


def test_literal_eval():
    with pytest.raises(ValueError, match="^$"):
        ast.literal_eval("pytest")

On Python 3.9 and below the above test fails but pytest doesn't crash.

Digging into the code with PDB the traceback passed to _pytest._code.code.FormattedExcInfo.repr_traceback_entry has a lineno of -1 which is used in a calculation to get a line_index of -6

@hroncok
Copy link
Member

hroncok commented Apr 22, 2021

We see more packages affected by this: e.g. parso

It makes testing on 3.10 very hard because you cannot tell why a test failed.

Can we get this merged please? What is missing?

@asottile
Copy link
Member

is it a regression in python 3.10? if so we should raise that before the beta period and probably get it fixed there instead of here

@hroncok
Copy link
Member

hroncok commented Apr 22, 2021

I am not sure. Would it help if I bisected the cpython commit that changed this?

@RonnyPfannschmidt
Copy link
Member

i do wonder if there is any way to unittest this

@hroncok
Copy link
Member

hroncok commented Apr 22, 2021

we should be able to use the example from the comment here, no?

@hroncok
Copy link
Member

hroncok commented Apr 22, 2021

I'll try to submit a test here.

@RonnyPfannschmidt
Copy link
Member

probably,

btw - @hroncok i think its possible to temporary work around this using --tb=native

@hroncok
Copy link
Member

hroncok commented Apr 22, 2021

Yes, --tb=native works, thanks!

Test added here. I had a hard time naming it and describing it. Suggestions welcome. It fails without @encukou's patch and succeeds with it.

@hroncok hroncok force-pushed the defensive-get_source branch from f5844a6 to 84c2e20 Compare April 22, 2021 17:17
@hroncok hroncok force-pushed the defensive-get_source branch from 84c2e20 to 0a75c8e Compare April 22, 2021 17:17
@RonnyPfannschmidt
Copy link
Member

imho this is goo for now - i'd like @asottile to lean in and i think a upstream report is necessary (and to link it in here and the code)

@asottile
Copy link
Member

haven't had a chance to dig into the actual bug, but here's the bisection failure:

python/cpython@3bd6035 python/cpython#24202

3bd6035b6baf1a7d51b7cc2c6bb2c81886236b67 is the first bad commit
commit 3bd6035b6baf1a7d51b7cc2c6bb2c81886236b67
Author: Mark Shannon <[email protected]>
Date:   Wed Jan 13 12:05:43 2021 +0000

    bpo-42908: Mark cleanup code at end of try-except and with artificial (#24202)
    
    * Mark bytecodes at end of try-except as artificial.
    
    * Make sure that the CFG is consistent throughout optimiization.
    
    * Extend line-number propagation logic so that implicit returns after 'try-except' or 'with' have the correct line numbers.
    
    * Update importlib

 Lib/test/test_dis.py          |    2 +-
 Lib/test/test_sys_settrace.py |   40 +
 Python/compile.c              |  135 +-
 Python/importlib.h            | 3153 ++++++++++++++---------------
 Python/importlib_external.h   | 4489 ++++++++++++++++++++---------------------
 Python/importlib_zipimport.h  | 1013 +++++-----
 6 files changed, 4473 insertions(+), 4359 deletions(-)
bisect run success

Copy link
Member

@nicoddemus nicoddemus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks everyone involved!

I agree we can get this in now so downstream users can use pytest in 3.10. We can improve the code and/or add more information later as needed.

@asottile
Copy link
Member

Thanks everyone involved!

I agree we can get this in now so downstream users can use pytest in 3.10. We can improve the code and/or add more information later as needed.

imo if we merge it I think we should plan to revert it when upstream fixes the issue

@nicoddemus
Copy link
Member

imo if we merge it I think we should plan to revert it when upstream fixes the issue

Sure. 👍

@asottile
Copy link
Member

here's the bpo issue, this is definitely a regression in 3.10 and I don't think pytest should make a code change for it: https://bugs.python.org/issue43933

here's a minimal reproduction for example without pytest:

class Boom:
    def __enter__(self):
        return self
    def __exit__(self, *_):
        raise AssertionError('boom!')


def main() -> int:
    with Boom():
        raise AssertionError('hi')


if __name__ == '__main__':
    exit(main())
$ python3.10 t.py 
Traceback (most recent call last):
  File "/home/asottile/workspace/cpython/t.py", line 10, in main
    raise AssertionError('hi')
AssertionError: hi

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/asottile/workspace/cpython/t.py", line 14, in <module>
    exit(main())
  File "/home/asottile/workspace/cpython/t.py", line -1, in main
  File "/home/asottile/workspace/cpython/t.py", line 5, in __exit__
    raise AssertionError('boom!')
AssertionError: boom!

notice we get a frame with a -1 line number 🙃

@RonnyPfannschmidt
Copy link
Member

imho we should, as broken pytest by python breaks other testing on that python

@asottile
Copy link
Member

imho we should, as broken pytest by python breaks other testing on that python

it's marked as a release blocker so this will never appear in actual released versions. note also that it doesn't break all testing of python, just for a very particular subset of exceptional cases

@nicoddemus
Copy link
Member

nicoddemus commented Apr 24, 2021

imho we should, as broken pytest by python breaks other testing on that python

I agree with that sentiment.

To make all points clear:

  1. This is making some downstream users' life harder.
  2. The fix is simple and was provided.
  3. It is trivial to revert this later once a new 3.10 release is made and the fix is no longer necessary.

I think we should help downstream packagers here, it doesn't really cost us much.

@asottile
Copy link
Member

alright, I'll handle reverting once this is fixed 👍

@asottile asottile merged commit 67af623 into pytest-dev:main Apr 25, 2021
@hroncok
Copy link
Member

hroncok commented Apr 25, 2021

Thank you all.

@nicoddemus
Copy link
Member

alright, I'll handle reverting once this is fixed

Great, thanks!

mgorny pushed a commit to mgorny/pytest that referenced this pull request Jun 2, 2021
Make code.FormattedExcinfo.get_source more defensive

(cherry picked from commit 67af623)
mgorny pushed a commit to mgorny/pytest that referenced this pull request Jun 3, 2021
Make code.FormattedExcinfo.get_source more defensive

(cherry picked from commit 67af623)
(Michał Górny: removed type hints for 6.2.x)
nicoddemus added a commit to nicoddemus/pytest that referenced this pull request Jun 3, 2021
@asottile
Copy link
Member

asottile commented Jun 3, 2021

this has been fixed upstream so here's the revert (I kept the test): #8729

asottile added a commit that referenced this pull request Jun 3, 2021
Revert "Merge pull request #8227 from encukou/defensive-get_source"
@brechtm
Copy link

brechtm commented Jun 19, 2021

I'm seeing this again with Python 3.10.0b3+ (heads/3.10:1b4addf3cb, Jun 19 2021, 01:52:02) [Clang 12.0.0 (clang-1200.0.32.29)]

pytest log
=================================================== test session starts ====================================================
platform darwin -- Python 3.10.0b3+, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /Users/brechtm/Documents/Code/rinohtype, configfile: setup.cfg
plugins: cov-2.12.1, xdist-2.3.0, forked-1.3.0
collected 0 items
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/main.py", line 269, in wrap_session
INTERNALERROR>     session.exitstatus = doit(config, session) or 0
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/main.py", line 322, in _main
INTERNALERROR>     config.hook.pytest_collection(session=session)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/hooks.py", line 286, in __call__
INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/manager.py", line 93, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/manager.py", line 84, in <lambda>
INTERNALERROR>     self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/callers.py", line 208, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/callers.py", line 80, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/callers.py", line 187, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/main.py", line 333, in pytest_collection
INTERNALERROR>     session.perform_collect()
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/main.py", line 634, in perform_collect
INTERNALERROR>     self.items.extend(self.genitems(node))
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/main.py", line 808, in genitems
INTERNALERROR>     rep = collect_one_node(node)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/runner.py", line 458, in collect_one_node
INTERNALERROR>     rep: CollectReport = ihook.pytest_make_collect_report(collector=collector)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/hooks.py", line 286, in __call__
INTERNALERROR>     return self._hookexec(self, self.get_hookimpls(), kwargs)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/manager.py", line 93, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook, methods, kwargs)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/manager.py", line 84, in <lambda>
INTERNALERROR>     self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/callers.py", line 203, in _multicall
INTERNALERROR>     gen.send(outcome)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/capture.py", line 797, in pytest_make_collect_report
INTERNALERROR>     rep = outcome.get_result()
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/callers.py", line 80, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/pluggy/callers.py", line 187, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/runner.py", line 360, in pytest_make_collect_report
INTERNALERROR>     errorinfo = collector.repr_failure(call.excinfo)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/nodes.py", line 472, in repr_failure
INTERNALERROR>     return self._repr_failure_py(excinfo, style=tbstyle)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/nodes.py", line 398, in _repr_failure_py
INTERNALERROR>     return excinfo.getrepr(
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/_code/code.py", line 648, in getrepr
INTERNALERROR>     return fmt.repr_excinfo(self)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/_code/code.py", line 905, in repr_excinfo
INTERNALERROR>     reprtraceback = self.repr_traceback(excinfo_)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/_code/code.py", line 846, in repr_traceback
INTERNALERROR>     reprentry = self.repr_traceback_entry(entry, einfo)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/_code/code.py", line 798, in repr_traceback_entry
INTERNALERROR>     s = self.get_source(source, line_index, excinfo, short=short)
INTERNALERROR>   File "/Users/brechtm/Documents/Code/rinohtype/.nox/unit-3-10-wheel/lib/python3.10/site-packages/_pytest/_code/code.py", line 727, in get_source
INTERNALERROR>     lines.append(space_prefix + source.lines[line_index].strip())
INTERNALERROR> IndexError: list index out of range

@asottile
Copy link
Member

@brechtm if you could share the code that would be helpful

@asottile
Copy link
Member

assuming this is a recent regression -- I've pinged this issue on this bpo: https://bugs.python.org/issue44297

@brechtm
Copy link

brechtm commented Jun 19, 2021

if you could share the code that would be helpful

Not sure whether you mean this:

$ git clone https://github.com/brechtm/rinohtype.git
$ poetry install
$ nox -s "unit-3.10(wheel)" -- -n 1

@asottile
Copy link
Member

here's the underlying traceback -- looks like importlib.metadata and/or genexprs?

Traceback (most recent call last):
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/_pytest/runner.py", line 311, in from_call
    result: Optional[TResult] = func()
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/_pytest/runner.py", line 341, in <lambda>
    call = CallInfo.from_call(lambda: list(collector.collect()), "collect")
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/_pytest/python.py", line 503, in collect
    self._inject_setup_module_fixture()
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/_pytest/python.py", line 516, in _inject_setup_module_fixture
    self.obj, ("setUpModule", "setup_module")
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/_pytest/python.py", line 291, in obj
    self._obj = obj = self._getobj()
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/_pytest/python.py", line 500, in _getobj
    return self._importtestmodule()
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/_pytest/python.py", line 578, in _importtestmodule
    mod = import_path(self.fspath, mode=importmode)
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/_pytest/pathlib.py", line 524, in import_path
    importlib.import_module(module_name)
  File "/home/asottile/workspace/cpython/prefix/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/_pytest/assertion/rewrite.py", line 170, in exec_module
    exec(co, module.__dict__)
  File "/tmp/rinohtype/tests/test_attribute.py", line 11, in <module>
    from rinoh.attribute import Attribute, Bool
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/rinoh/__init__.py", line 41, in <module>
    from . import resource
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/rinoh/resource.py", line 205, in <module>
    from .template import DocumentTemplate
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/rinoh/template.py", line 42, in <module>
    from .stylesheets import sphinx
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/rinoh/stylesheets/__init__.py", line 42, in <module>
    .format(stylesheet.description, stylesheet))
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/rinoh/style.py", line 670, in __str__
    for name, entry_point in self.installed_resources:
  File "/tmp/rinohtype/venv/lib/python3.10/site-packages/rinoh/resource.py", line 54, in installed_resources
    for entry_point in ilm.entry_points()[cls.entry_point_group]:
  File "/home/asottile/workspace/cpython/prefix/lib/python3.10/importlib/metadata/__init__.py", line 979, in entry_points
    return SelectableGroups.load(eps).select(**params)
  File "/home/asottile/workspace/cpython/prefix/lib/python3.10/importlib/metadata/__init__.py", line 437, in load
    ordered = sorted(eps, key=by_group)
  File "/home/asottile/workspace/cpython/prefix/lib/python3.10/importlib/metadata/__init__.py", line -1, in <genexpr>
  File "/home/asottile/workspace/cpython/prefix/lib/python3.10/importlib/metadata/_itertools.py", line 16, in unique_everseen
    k = key(element)
  File "/home/asottile/workspace/cpython/prefix/lib/python3.10/importlib/metadata/__init__.py", line 600, in _normalized_name
    return Prepared.normalize(self.name)
  File "/home/asottile/workspace/cpython/prefix/lib/python3.10/importlib/metadata/__init__.py", line 841, in normalize
    return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_')
  File "/home/asottile/workspace/cpython/prefix/lib/python3.10/re.py", line 187, in sub
    return _compile(pattern, flags).sub(repl, string, count)
TypeError: expected string or bytes-like object

@brechtm
Copy link

brechtm commented Jun 19, 2021

To be sure, I checked with Python 3.10.0b2. No issues there.

@asottile
Copy link
Member

I think you're actually hitting the cross section of one (annoying, intentional?) importlib.metadata breaking change as well as a regression in the traceback lines -- it appears importlib.metadata in 3.10b3 is unhappy with the custom DynamicRinohDistribution having a name=None -- and so that raises the stacktrace which includes that frame missing a line number (the regression)

@brechtm
Copy link

brechtm commented Jun 19, 2021

@asottile Wow, thanks for the analysis! I guess I'll have to set a name...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants