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

3.11 branch: column >= -1 assertion failure with pytest rewriting #94694

Open
The-Compiler opened this issue Jul 8, 2022 · 43 comments
Open

3.11 branch: column >= -1 assertion failure with pytest rewriting #94694

The-Compiler opened this issue Jul 8, 2022 · 43 comments
Labels
3.12 bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-crash A hard crash of the interpreter, possibly with a core dump

Comments

@The-Compiler
Copy link
Contributor

The-Compiler commented Jul 8, 2022

Crash report

When running pytest in e.g. the pytest repository on the current Python 3.11 branch, it aborts, perhaps similarly to #93387 or #92597 somehow...

I've been unable to get a minimal reproducer so far, but this will reproduce it:

  • git clone https://github.com/pytest-dev/pytest
  • cd pytest
  • ~/proj/cpython/python -m venv .venv (with the current 3.11 branch)
  • .venv/bin/pip install -e ".[testing]"
  • .venv/bin/pytest

I was able to bisect this to df091e1:

[3.11] GH-93662: Make sure that column offsets are correct in multi-line method calls. (GH-93673) (#93895)

cc @iritkatriel @markshannon @pablogsal

Note this (thankfully) only seems to affect --with-pydebug builds.

Error messages

This assertion seems to fail:

assert(column >= -1);

Unfortunately I haven't been able to get the column value, as it was apparently optimized out...

Python stack:

Current thread 0x00007f1b72048740 (most recent call first):
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/assertion/rewrite.py", line 361 in _rewrite_test
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/assertion/rewrite.py", line 159 in exec_module
  File "<frozen importlib._bootstrap>", line 690 in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1149 in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1178 in _find_and_load
  File "<frozen importlib._bootstrap>", line 1206 in _gcd_import
  File "/home/florian/proj/cpython/Lib/importlib/__init__.py", line 126 in import_module
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/pathlib.py", line 533 in import_path
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/python.py", line 608 in _importtestmodule
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/python.py", line 519 in _getobj
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/python.py", line 301 in obj
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/python.py", line 536 in _inject_setup_module_fixture
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/python.py", line 522 in collect
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/runner.py", line 369 in <lambda>
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/runner.py", line 338 in from_call
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/runner.py", line 369 in pytest_make_collect_report
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pluggy/_callers.py", line 39 in _multicall
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pluggy/_manager.py", line 80 in _hookexec
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pluggy/_hooks.py", line 265 in __call__
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/runner.py", line 537 in collect_one_node
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/main.py", line 824 in genitems
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/main.py", line 657 in perform_collect
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/main.py", line 332 in pytest_collection
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pluggy/_callers.py", line 39 in _multicall
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pluggy/_manager.py", line 80 in _hookexec
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pluggy/_hooks.py", line 265 in __call__
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/main.py", line 321 in _main
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/main.py", line 268 in wrap_session
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/main.py", line 315 in pytest_cmdline_main
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pluggy/_callers.py", line 39 in _multicall
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pluggy/_manager.py", line 80 in _hookexec
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pluggy/_hooks.py", line 265 in __call__
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/config/__init__.py", line 164 in main
  File "/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/_pytest/config/__init__.py", line 187 in console_main
  File "/home/florian/tmp/python-pytest/.venv/bin/pytest", line 8 in <module>
[1]    822828 IOT instruction (core dumped)  ~/tmp/python-pytest/.venv/bin/pytest

C stack:

#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at pthread_kill.c:44
#1  0x00007ffff7c8e3d3 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at pthread_kill.c:78
#2  0x00007ffff7c3e838 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3  0x00007ffff7c28535 in __GI_abort () at abort.c:79
#4  0x00007ffff7c2845c in __assert_fail_base (fmt=0x7ffff7dbfe70 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x555555916af6 "column >= -1", file=0x555555916663 "Python/compile.c", line=7584, function=<optimized out>)
    at assert.c:92
#5  0x00007ffff7c37366 in __GI___assert_fail (assertion=assertion@entry=0x555555916af6 "column >= -1", file=file@entry=0x555555916663 "Python/compile.c", line=line@entry=7584, 
    function=function@entry=0x5555559145b0 <__PRETTY_FUNCTION__.11> "write_location_info_entry") at assert.c:101
#6  0x00005555557c7016 in write_location_info_entry (a=a@entry=0x7fffffffa9d0, i=i@entry=0x5555562812f8, isize=isize@entry=8) at Python/compile.c:7584
#7  0x00005555557c7106 in assemble_emit_location (a=a@entry=0x7fffffffa9d0, i=0x5555562812f8) at Python/compile.c:7614
#8  0x00005555557c9a7a in assemble (c=c@entry=0x7fffffffab70, addNone=addNone@entry=1) at Python/compile.c:8425
#9  0x00005555557d0bab in compiler_function (c=0x7fffffffab70, s=<optimized out>, is_async=is_async@entry=0) at Python/compile.c:2656
#10 0x00005555557d0d01 in compiler_visit_stmt (c=c@entry=0x7fffffffab70, s=0x555556318030) at Python/compile.c:4047
#11 0x00005555557d0fc8 in compiler_body (c=c@entry=0x7fffffffab70, stmts=0x55555620bdc0) at Python/compile.c:2164
#12 0x00005555557d1540 in compiler_mod (c=c@entry=0x7fffffffab70, mod=mod@entry=0x555556321b90) at Python/compile.c:2181
#13 0x00005555557d4ab1 in _PyAST_Compile (mod=mod@entry=0x555556321b90, filename=filename@entry='/home/florian/proj/pytest/testing/test_capture.py', flags=flags@entry=0x7fffffffac18, optimize=optimize@entry=-1, 
    arena=arena@entry=0x7ffff58ec820) at Python/compile.c:581
#14 0x00005555557a4d2b in builtin_compile_impl (module=module@entry=<module at remote 0x7ffff779f1d0>, 
    source=source@entry=<Module(body=[<Import(names=[<alias(name='builtins', asname='@py_builtins', lineno=1, col_offset=0) at remote 0x7ffff5d22440>], lineno=1, col_offset=0) at remote 0x7ffff5d22f80>, <Import(names=[<alias(name='_pytest.assertion.rewrite', asname='@pytest_ar', lineno=1, col_offset=0) at remote 0x7ffff5d21ef0>], lineno=1, col_offset=0) at remote 0x7ffff5d28460>, <Import(names=[<alias(name='contextlib', asname=None, lineno=1, col_offset=7, end_lineno=1, end_col_offset=17) at remote 0x7ffff5dea760>], lineno=1, col_offset=0, end_lineno=1, end_col_offset=17) at remote 0x7ffff5dea7b0>, <Import(names=[<alias(name='io', asname=None, lineno=2, col_offset=7, end_lineno=2, end_col_offset=9) at remote 0x7ffff5dea6c0>], lineno=2, col_offset=0, end_lineno=2, end_col_offset=9) at remote 0x7ffff5dea710>, <Import(names=[<alias(name='os', asname=None, lineno=3, col_offset=7, end_lineno=3, end_col_offset=9) at remote 0x7ffff5dea620>], lineno=3, col_offset=0, end_lineno=3, end_col_offset=9) at remote 0x7ffff5dea670>, <Import(names=[<...(truncated), filename='/home/florian/proj/pytest/testing/test_capture.py', mode=mode@entry=0x555555af3810 <const_str_exec+48> "exec", 
    flags=flags@entry=0, dont_inherit=dont_inherit@entry=1, optimize=-1, feature_version=-1) at Python/bltinmodule.c:818
#15 0x00005555557a5008 in builtin_compile (module=<module at remote 0x7ffff779f1d0>, args=<optimized out>, args@entry=0x7ffff7e6d7d8, nargs=nargs@entry=3, kwnames=kwnames@entry=('dont_inherit',)) at Python/clinic/bltinmodule.c.h:328
#16 0x0000555555717156 in cfunction_vectorcall_FASTCALL_KEYWORDS (func=<built-in method compile of module object at remote 0x7ffff779f1d0>, args=0x7ffff7e6d7d8, nargsf=<optimized out>, kwnames=('dont_inherit',))
    at Objects/methodobject.c:443
#17 0x00005555556d059f in _PyObject_VectorcallTstate (tstate=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<built-in method compile of module object at remote 0x7ffff779f1d0>, args=args@entry=0x7ffff7e6d7d8, 
    nargsf=9223372036854775811, kwnames=kwnames@entry=('dont_inherit',)) at ./Include/internal/pycore_call.h:92
#18 0x00005555556d0676 in PyObject_Vectorcall (callable=callable@entry=<built-in method compile of module object at remote 0x7ffff779f1d0>, args=args@entry=0x7ffff7e6d7d8, nargsf=<optimized out>, kwnames=kwnames@entry=('dont_inherit',))
    at Objects/call.c:299
#19 0x00005555557b8fef in _PyEval_EvalFrameDefault (tstate=0x555555b2f5e8 <_PyRuntime+166312>, frame=0x7ffff7e6d748, throwflag=<optimized out>) at Python/ceval.c:4773
#20 0x00005555557bd6cd in _PyEval_EvalFrame (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, frame=frame@entry=0x7ffff7e6d0e8, throwflag=throwflag@entry=0) at ./Include/internal/pycore_ceval.h:72
#21 0x00005555557bd7ce in _PyEval_Vector (tstate=0x555555b2f5e8 <_PyRuntime+166312>, func=0x7ffff6bac7e0, locals=locals@entry=0x0, args=0x7fffffffaf98, argcount=<optimized out>, kwnames=0x0) at Python/ceval.c:6421
#22 0x00005555556d023e in _PyFunction_Vectorcall (func=<optimized out>, stack=<optimized out>, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/call.c:393
#23 0x00005555556d059f in _PyObject_VectorcallTstate (tstate=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<function at remote 0x7ffff6bac7e0>, args=args@entry=0x7fffffffaf98, nargsf=nargsf@entry=9223372036854775809, 
    kwnames=kwnames@entry=0x0) at ./Include/internal/pycore_call.h:92
#24 0x00005555556d06e7 in PyObject_CallOneArg (func=func@entry=<function at remote 0x7ffff6bac7e0>, 
    arg=arg@entry=<Module(keywords=<NodeKeywords at remote 0x7ffff6683250>, own_markers=[], extra_keyword_matches=set(), stash=<Stash at remote 0x7ffff6698e50>) at remote 0x7ffff66a43c0>) at Objects/call.c:376
#25 0x00005555556dc4aa in property_descr_get (self=self@entry=<property at remote 0x7ffff6ba50f0>, 
    obj=obj@entry=<Module(keywords=<NodeKeywords at remote 0x7ffff6683250>, own_markers=[], extra_keyword_matches=set(), stash=<Stash at remote 0x7ffff6698e50>) at remote 0x7ffff66a43c0>, type=<optimized out>)
    at Objects/descrobject.c:1630
#26 0x000055555571c830 in _PyObject_GenericGetAttrWithDict (obj=<Module(keywords=<NodeKeywords at remote 0x7ffff6683250>, own_markers=[], extra_keyword_matches=set(), stash=<Stash at remote 0x7ffff6698e50>) at remote 0x7ffff66a43c0>, 
    name='obj', dict=dict@entry=0x0, suppress=suppress@entry=0) at Objects/object.c:1274
#27 0x000055555571cca5 in PyObject_GenericGetAttr (obj=<optimized out>, name=<optimized out>) at Objects/object.c:1362
#28 0x000055555571c317 in PyObject_GetAttr (v=v@entry=<Module(keywords=<NodeKeywords at remote 0x7ffff6683250>, own_markers=[], extra_keyword_matches=set(), stash=<Stash at remote 0x7ffff6698e50>) at remote 0x7ffff66a43c0>, name='obj')
    Objects/object.c:917
#29 0x00005555557b3781 in _PyEval_EvalFrameDefault (tstate=0x555555b2f5e8 <_PyRuntime+166312>, frame=0x7ffff7e6d048, throwflag=<optimized out>) at Python/ceval.c:3468
#30 0x00005555557bd6cd in _PyEval_EvalFrame (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, frame=frame@entry=0x7ffff7e6cdb0, throwflag=throwflag@entry=0) at ./Include/internal/pycore_ceval.h:72
#31 0x00005555557bd7ce in _PyEval_Vector (tstate=0x555555b2f5e8 <_PyRuntime+166312>, func=0x7ffff6b60b50, locals=locals@entry=0x0, args=0x7ffff6682098, argcount=<optimized out>, kwnames=0x0) at Python/ceval.c:6421
#32 0x00005555556d023e in _PyFunction_Vectorcall (func=<optimized out>, stack=<optimized out>, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/call.c:393
#33 0x00005555556cfde3 in _PyVectorcall_Call (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, func=0x5555556d01ee <_PyFunction_Vectorcall>, callable=callable@entry=<function at remote 0x7ffff6b60b50>, tuple=tuple@entry=(<Module(keywords=<NodeKeywords at remote 0x7ffff6683250>, own_markers=[], extra_keyword_matches=set(), stash=<Stash at remote 0x7ffff6698e50>) at remote 0x7ffff66a43c0>,), kwargs=kwargs@entry=0x0) at Objects/call.c:245
#34 0x00005555556d0180 in _PyObject_Call (tstate=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<function at remote 0x7ffff6b60b50>, args=args@entry=(<Module(keywords=<NodeKeywords at remote 0x7ffff6683250>, own_markers=[], extra_keyword_matches=set(), stash=<Stash at remote 0x7ffff6698e50>) at remote 0x7ffff66a43c0>,), kwargs=kwargs@entry=0x0) at Objects/call.c:328
#35 0x00005555556d01c8 in PyObject_Call (callable=callable@entry=<function at remote 0x7ffff6b60b50>, args=args@entry=(<Module(keywords=<NodeKeywords at remote 0x7ffff6683250>, own_markers=[], extra_keyword_matches=set(), stash=<Stash at remote 0x7ffff6698e50>) at remote 0x7ffff66a43c0>,), kwargs=kwargs@entry=0x0) at Objects/call.c:355
#36 0x00005555557ab8c2 in do_call_core (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, func=func@entry=<function at remote 0x7ffff6b60b50>, callargs=callargs@entry=(<Module(keywords=<NodeKeywords at remote 0x7ffff6683250>, own_markers=[], extra_keyword_matches=set(), stash=<Stash at remote 0x7ffff6698e50>) at remote 0x7ffff66a43c0>,), kwdict=kwdict@entry=0x0, use_tracing=0) at Python/ceval.c:7318
#37 0x00005555557bbc54 in _PyEval_EvalFrameDefault (tstate=0x555555b2f5e8 <_PyRuntime+166312>, frame=0x7ffff7e6ccc0, throwflag=<optimized out>) at Python/ceval.c:5378
#38 0x00005555557bd6cd in _PyEval_EvalFrame (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, frame=frame@entry=0x7ffff7e6cb78, throwflag=throwflag@entry=0) at ./Include/internal/pycore_ceval.h:72
#39 0x00005555557bd7ce in _PyEval_Vector (tstate=0x555555b2f5e8 <_PyRuntime+166312>, func=0x7ffff7242e60, locals=locals@entry=0x0, args=0x7ffff7793e58, argcount=<optimized out>, kwnames=('collector',)) at Python/ceval.c:6421
#40 0x00005555556d023e in _PyFunction_Vectorcall (func=<optimized out>, stack=<optimized out>, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/call.c:393
#41 0x00005555556d1b4a in _PyObject_FastCallDictTstate (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<function at remote 0x7ffff7242e60>, args=args@entry=0x7fffffffb550, nargsf=nargsf@entry=1, kwargs=kwargs@entry={'collector': <Module(keywords=<NodeKeywords at remote 0x7ffff6683250>, own_markers=[], extra_keyword_matches=set(), stash=<Stash at remote 0x7ffff6698e50>) at remote 0x7ffff66a43c0>}) at Objects/call.c:152
#42 0x00005555556d1d05 in _PyObject_Call_Prepend (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<function at remote 0x7ffff7242e60>, 
    obj=obj@entry=<_HookCaller(name='pytest_make_collect_report', _wrappers=[<HookImpl(function=<method at remote 0x7ffff67ae630>, argnames=('collector',), kwargnames=(), plugin=<CaptureManager(_method='fd', _global_capturing=<MultiCapture(in_=<FDCapture(targetfd=0, targetfd_invalid=None, targetfd_save=3, tmpfile=<_io.TextIOWrapper at remote 0x7ffff6911400>, syscapture=<SysCapture(_old=<_io.TextIOWrapper at remote 0x7ffff77fe7b0>, name='stdin', tmpfile=<DontReadFromInput() at remote 0x7ffff67b7df0>, _state='started') at remote 0x7ffff67a13c0>, _state='started') at remote 0x7ffff67a1230>, out=<FDCapture(targetfd=1, targetfd_invalid=None, targetfd_save=5, tmpfile=<EncodedFile at remote 0x7ffff6911220>, syscapture=<SysCapture(_old=<_io.TextIOWrapper at remote 0x7ffff77fe8a0>, name='stdout', tmpfile=<...>, _state='started') at remote 0x7ffff67b7e90>, _state='started') at remote 0x7ffff67b7990>, err=<FDCapture(targetfd=2, targetfd_invalid=None, targetfd_save=7, tmpfile=<EncodedFile at remote 0x7ffff67726c0>, syscapture=<SysCapture(...(truncated), args=args@entry=(), kwargs=kwargs@entry={'collector': <Module(keywords=<NodeKeywords at remote 0x7ffff6683250>, own_markers=[], extra_keyword_matches=set(), stash=<Stash at remote 0x7ffff6698e50>) at remote 0x7ffff66a43c0>}) at Objects/call.c:482
#43 0x0000555555739abc in slot_tp_call (
    self=<_HookCaller(name='pytest_make_collect_report', _wrappers=[<HookImpl(function=<method at remote 0x7ffff67ae630>, argnames=('collector',), kwargnames=(), plugin=<CaptureManager(_method='fd', _global_capturing=<MultiCapture(in_=<FDCapture(targetfd=0, targetfd_invalid=None, targetfd_save=3, tmpfile=<_io.TextIOWrapper at remote 0x7ffff6911400>, syscapture=<SysCapture(_old=<_io.TextIOWrapper at remote 0x7ffff77fe7b0>, name='stdin', tmpfile=<DontReadFromInput() at remote 0x7ffff67b7df0>, _state='started') at remote 0x7ffff67a13c0>, _state='started') at remote 0x7ffff67a1230>, out=<FDCapture(targetfd=1, targetfd_invalid=None, targetfd_save=5, tmpfile=<EncodedFile at remote 0x7ffff6911220>, syscapture=<SysCapture(_old=<_io.TextIOWrapper at remote 0x7ffff77fe8a0>, name='stdout', tmpfile=<...>, _state='started') at remote 0x7ffff67b7e90>, _state='started') at remote 0x7ffff67b7990>, err=<FDCapture(targetfd=2, targetfd_invalid=None, targetfd_save=7, tmpfile=<EncodedFile at remote 0x7ffff67726c0>, syscapture=<SysCapture(...(truncated), args=(), kwds={'collector': <Module(keywords=<NodeKeywords at remote 0x7ffff6683250>, own_markers=[], extra_keyword_matches=set(), stash=<Stash at remote 0x7ffff6698e50>) at remote 0x7ffff66a43c0>}) at Objects/typeobject.c:7598
#44 0x00005555556d03e3 in _PyObject_MakeTpCall (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, 
    callable=callable@entry=<_HookCaller(name='pytest_make_collect_report', _wrappers=[<HookImpl(function=<method at remote 0x7ffff67ae630>, argnames=('collector',), kwargnames=(), plugin=<CaptureManager(_method='fd', _global_capturing=<MultiCapture(in_=<FDCapture(targetfd=0, targetfd_invalid=None, targetfd_save=3, tmpfile=<_io.TextIOWrapper at remote 0x7ffff6911400>, syscapture=<SysCapture(_old=<_io.TextIOWrapper at remote 0x7ffff77fe7b0>, name='stdin', tmpfile=<DontReadFromInput() at remote 0x7ffff67b7df0>, _state='started') at remote 0x7ffff67a13c0>, _state='started') at remote 0x7ffff67a1230>, out=<FDCapture(targetfd=1, targetfd_invalid=None, targetfd_save=5, tmpfile=<EncodedFile at remote 0x7ffff6911220>, syscapture=<SysCapture(_old=<_io.TextIOWrapper at remote 0x7ffff77fe8a0>, name='stdout', tmpfile=<...>, _state='started') at remote 0x7ffff67b7e90>, _state='started') at remote 0x7ffff67b7990>, err=<FDCapture(targetfd=2, targetfd_invalid=None, targetfd_save=7, tmpfile=<EncodedFile at remote 0x7ffff67726c0>, syscapture=<SysCapture(...(truncated), args=args@entry=0x7ffff7e6cb60, nargs=<optimized out>, keywords=keywords@entry=('collector',)) at Objects/call.c:214
#45 0x00005555556d061f in _PyObject_VectorcallTstate (tstate=0x555555b2f5e8 <_PyRuntime+166312>, 
    callable=callable@entry=<_HookCaller(name='pytest_make_collect_report', _wrappers=[<HookImpl(function=<method at remote 0x7ffff67ae630>, argnames=('collector',), kwargnames=(), plugin=<CaptureManager(_method='fd', _global_capturing=<MultiCapture(in_=<FDCapture(targetfd=0, targetfd_invalid=None, targetfd_save=3, tmpfile=<_io.TextIOWrapper at remote 0x7ffff6911400>, syscapture=<SysCapture(_old=<_io.TextIOWrapper at remote 0x7ffff77fe7b0>, name='stdin', tmpfile=<DontReadFromInput() at remote 0x7ffff67b7df0>, _state='started') at remote 0x7ffff67a13c0>, _state='started') at remote 0x7ffff67a1230>, out=<FDCapture(targetfd=1, targetfd_invalid=None, targetfd_save=5, tmpfile=<EncodedFile at remote 0x7ffff6911220>, syscapture=<SysCapture(_old=<_io.TextIOWrapper at remote 0x7ffff77fe8a0>, name='stdout', tmpfile=<...>, _state='started') at remote 0x7ffff67b7e90>, _state='started') at remote 0x7ffff67b7990>, err=<FDCapture(targetfd=2, targetfd_invalid=None, targetfd_save=7, tmpfile=<EncodedFile at remote 0x7ffff67726c0>, syscapture=<SysCapture(...(truncated), args=args@entry=0x7ffff7e6cb60, nargsf=<optimized out>, kwnames=kwnames@entry=('collector',)) at ./Include/internal/pycore_call.h:90
#46 0x00005555556d0676 in PyObject_Vectorcall (
    callable=callable@entry=<_HookCaller(name='pytest_make_collect_report', _wrappers=[<HookImpl(function=<method at remote 0x7ffff67ae630>, argnames=('collector',), kwargnames=(), plugin=<CaptureManager(_method='fd', _global_capturing=<MultiCapture(in_=<FDCapture(targetfd=0, targetfd_invalid=None, targetfd_save=3, tmpfile=<_io.TextIOWrapper at remote 0x7ffff6911400>, syscapture=<SysCapture(_old=<_io.TextIOWrapper at remote 0x7ffff77fe7b0>, name='stdin', tmpfile=<DontReadFromInput() at remote 0x7ffff67b7df0>, _state='started') at remote 0x7ffff67a13c0>, _state='started') at remote 0x7ffff67a1230>, out=<FDCapture(targetfd=1, targetfd_invalid=None, targetfd_save=5, tmpfile=<EncodedFile at remote 0x7ffff6911220>, syscapture=<SysCapture(_old=<_io.TextIOWrapper at remote 0x7ffff77fe8a0>, name='stdout', tmpfile=<...>, _state='started') at remote 0x7ffff67b7e90>, _state='started') at remote 0x7ffff67b7990>, err=<FDCapture(targetfd=2, targetfd_invalid=None, targetfd_save=7, tmpfile=<EncodedFile at remote 0x7ffff67726c0>, syscapture=<SysCapture(...(truncated), args=args@entry=0x7ffff7e6cb60, nargsf=<optimized out>, kwnames=kwnames@entry=('collector',)) at Objects/call.c:299
#47 0x00005555557b8fef in _PyEval_EvalFrameDefault (tstate=0x555555b2f5e8 <_PyRuntime+166312>, frame=0x7ffff7e6cae8, throwflag=<optimized out>) at Python/ceval.c:4773
#48 0x00005555556e64ff in _PyEval_EvalFrame (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, frame=frame@entry=0x7ffff6684ca0, throwflag=throwflag@entry=0) at ./Include/internal/pycore_ceval.h:72
#49 0x00005555556e6831 in gen_send_ex2 (gen=0x7ffff6684c50, arg=arg@entry=0x0, presult=presult@entry=0x7fffffffb840, exc=exc@entry=0, closing=closing@entry=0) at Objects/genobject.c:219
#50 0x00005555556e7e64 in gen_iternext (gen=<optimized out>) at Objects/genobject.c:594
#51 0x00005555556f93d3 in list_extend (self=self@entry=0x7ffff676b430, iterable=iterable@entry=<generator at remote 0x7ffff6684c50>) at Objects/listobject.c:960
#52 0x00005555557bb04e in _PyEval_EvalFrameDefault (tstate=0x555555b2f5e8 <_PyRuntime+166312>, frame=0x7ffff7e6c9f8, throwflag=<optimized out>) at Python/ceval.c:5223
#53 0x00005555557bd6cd in _PyEval_EvalFrame (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, frame=frame@entry=0x7ffff7e6c998, throwflag=throwflag@entry=0) at ./Include/internal/pycore_ceval.h:72
#54 0x00005555557bd7ce in _PyEval_Vector (tstate=0x555555b2f5e8 <_PyRuntime+166312>, func=0x7ffff6b615a0, locals=locals@entry=0x0, args=0x7ffff6681878, argcount=<optimized out>, kwnames=0x0) at Python/ceval.c:6421
#55 0x00005555556d023e in _PyFunction_Vectorcall (func=<optimized out>, stack=<optimized out>, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/call.c:393
#56 0x00005555556cfde3 in _PyVectorcall_Call (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, func=0x5555556d01ee <_PyFunction_Vectorcall>, callable=callable@entry=<function at remote 0x7ffff6b615a0>, tuple=tuple@entry=(<Session at remote 0x7ffff698c180>,), kwargs=kwargs@entry=0x0) at Objects/call.c:245
#57 0x00005555556d0180 in _PyObject_Call (tstate=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<function at remote 0x7ffff6b615a0>, args=args@entry=(<Session at remote 0x7ffff698c180>,), kwargs=kwargs@entry=0x0) at Objects/call.c:328
#58 0x00005555556d01c8 in PyObject_Call (callable=callable@entry=<function at remote 0x7ffff6b615a0>, args=args@entry=(<Session at remote 0x7ffff698c180>,), kwargs=kwargs@entry=0x0) at Objects/call.c:355
#59 0x00005555557ab8c2 in do_call_core (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, func=func@entry=<function at remote 0x7ffff6b615a0>, callargs=callargs@entry=(<Session at remote 0x7ffff698c180>,), kwdict=kwdict@entry=0x0, use_tracing=0) at Python/ceval.c:7318
#60 0x00005555557bbc54 in _PyEval_EvalFrameDefault (tstate=0x555555b2f5e8 <_PyRuntime+166312>, frame=0x7ffff7e6c8a8, throwflag=<optimized out>) at Python/ceval.c:5378
#61 0x00005555557bd6cd in _PyEval_EvalFrame (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, frame=frame@entry=0x7ffff7e6c760, throwflag=throwflag@entry=0) at ./Include/internal/pycore_ceval.h:72
#62 0x00005555557bd7ce in _PyEval_Vector (tstate=0x555555b2f5e8 <_PyRuntime+166312>, func=0x7ffff7242e60, locals=locals@entry=0x0, args=0x7ffff7792da8, argcount=<optimized out>, kwnames=('session',)) at Python/ceval.c:6421
#63 0x00005555556d023e in _PyFunction_Vectorcall (func=<optimized out>, stack=<optimized out>, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/call.c:393
#64 0x00005555556d1b4a in _PyObject_FastCallDictTstate (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<function at remote 0x7ffff7242e60>, args=args@entry=0x7fffffffbd50, nargsf=nargsf@entry=1, kwargs=kwargs@entry={'session': <Session at remote 0x7ffff698c180>}) at Objects/call.c:152
#65 0x00005555556d1d05 in _PyObject_Call_Prepend (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<function at remote 0x7ffff7242e60>, 
    obj=obj@entry=<_HookCaller(name='pytest_collection', _wrappers=[<HookImpl(function=<method at remote 0x7ffff68afd10>, argnames=(), kwargnames=(...), plugin=<Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, ...(truncated), args=args@entry=(), kwargs=kwargs@entry={'session': <Session at remote 0x7ffff698c180>}) at Objects/call.c:482
#66 0x0000555555739abc in slot_tp_call (
    self=<_HookCaller(name='pytest_collection', _wrappers=[<HookImpl(function=<method at remote 0x7ffff68afd10>, argnames=(), kwargnames=(...), plugin=<Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, ...(truncated), args=(), kwds={'session': <Session at remote 0x7ffff698c180>}) at Objects/typeobject.c:7598
#67 0x00005555556d03e3 in _PyObject_MakeTpCall (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, 
    callable=callable@entry=<_HookCaller(name='pytest_collection', _wrappers=[<HookImpl(function=<method at remote 0x7ffff68afd10>, argnames=(), kwargnames=(...), plugin=<Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, ...(truncated), args=args@entry=0x7ffff7e6c758, nargs=<optimized out>, keywords=keywords@entry=('session',)) at Objects/call.c:214
#68 0x00005555556d061f in _PyObject_VectorcallTstate (tstate=0x555555b2f5e8 <_PyRuntime+166312>, 
    callable=callable@entry=<_HookCaller(name='pytest_collection', _wrappers=[<HookImpl(function=<method at remote 0x7ffff68afd10>, argnames=(), kwargnames=(...), plugin=<Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, ...(truncated), args=args@entry=0x7ffff7e6c758, nargsf=<optimized out>, kwnames=kwnames@entry=('session',)) at ./Include/internal/pycore_call.h:90
#69 0x00005555556d0676 in PyObject_Vectorcall (
    callable=callable@entry=<_HookCaller(name='pytest_collection', _wrappers=[<HookImpl(function=<method at remote 0x7ffff68afd10>, argnames=(), kwargnames=(...), plugin=<Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, ...(truncated), args=args@entry=0x7ffff7e6c758, nargsf=<optimized out>, kwnames=kwnames@entry=('session',)) at Objects/call.c:299
#70 0x00005555557b8fef in _PyEval_EvalFrameDefault (tstate=0x555555b2f5e8 <_PyRuntime+166312>, frame=0x7ffff7e6c6f0, throwflag=<optimized out>) at Python/ceval.c:4773
#71 0x00005555557bd6cd in _PyEval_EvalFrame (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, frame=frame@entry=0x7ffff7e6c5b8, throwflag=throwflag@entry=0) at ./Include/internal/pycore_ceval.h:72
#72 0x00005555557bd7ce in _PyEval_Vector (tstate=0x555555b2f5e8 <_PyRuntime+166312>, func=0x7ffff6b61440, locals=locals@entry=0x0, args=0x7ffff6775238, argcount=<optimized out>, kwnames=0x0) at Python/ceval.c:6421
#73 0x00005555556d023e in _PyFunction_Vectorcall (func=<optimized out>, stack=<optimized out>, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/call.c:393
#74 0x00005555556cfde3 in _PyVectorcall_Call (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, func=0x5555556d01ee <_PyFunction_Vectorcall>, callable=callable@entry=<function at remote 0x7ffff6b61440>, 
    tuple=tuple@entry=(<Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, lsof=False, runpytest='inprocess', markers=False, usepdb=False, usepdb_cls=None, trace=False, lf=False, failedfirst=False, newfirst=False, ca...(truncated), kwargs=kwargs@entry=0x0) at Objects/call.c:245
#75 0x00005555556d0180 in _PyObject_Call (tstate=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<function at remote 0x7ffff6b61440>, 
    args=args@entry=(<Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, lsof=False, runpytest='inprocess', markers=False, usepdb=False, usepdb_cls=None, trace=False, lf=False, failedfirst=False, newfirst=False, ca...(truncated), kwargs=kwargs@entry=0x0) at Objects/call.c:328
#76 0x00005555556d01c8 in PyObject_Call (callable=callable@entry=<function at remote 0x7ffff6b61440>, 
    args=args@entry=(<Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, lsof=False, runpytest='inprocess', markers=False, usepdb=False, usepdb_cls=None, trace=False, lf=False, failedfirst=False, newfirst=False, ca...(truncated), kwargs=kwargs@entry=0x0) at Objects/call.c:355
#77 0x00005555557ab8c2 in do_call_core (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, func=func@entry=<function at remote 0x7ffff6b61440>, 
    callargs=callargs@entry=(<Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, lsof=False, runpytest='inprocess', markers=False, usepdb=False, usepdb_cls=None, trace=False, lf=False, failedfirst=False, newfirst=False, ca...(truncated), kwdict=kwdict@entry=0x0, use_tracing=0) at Python/ceval.c:7318
#78 0x00005555557bbc54 in _PyEval_EvalFrameDefault (tstate=0x555555b2f5e8 <_PyRuntime+166312>, frame=0x7ffff7e6c4c8, throwflag=<optimized out>) at Python/ceval.c:5378
#79 0x00005555557bd6cd in _PyEval_EvalFrame (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, frame=frame@entry=0x7ffff7e6c380, throwflag=throwflag@entry=0) at ./Include/internal/pycore_ceval.h:72
#80 0x00005555557bd7ce in _PyEval_Vector (tstate=0x555555b2f5e8 <_PyRuntime+166312>, func=0x7ffff7242e60, locals=locals@entry=0x0, args=0x7ffff7792c28, argcount=<optimized out>, kwnames=('config',)) at Python/ceval.c:6421
--Type <RET> for more, q to quit, c to continue without paging--
#81 0x00005555556d023e in _PyFunction_Vectorcall (func=<optimized out>, stack=<optimized out>, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/call.c:393
#82 0x00005555556d1b4a in _PyObject_FastCallDictTstate (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<function at remote 0x7ffff7242e60>, args=args@entry=0x7fffffffc350, nargsf=nargsf@entry=1, 
    kwargs=kwargs@entry={'config': <Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, lsof=False, runpytest='inprocess', markers=False, usepdb=False, usepdb_cls=None, trace=False, lf=False, failedfirst=False, newfirst...(truncated)) at Objects/call.c:152
#83 0x00005555556d1d05 in _PyObject_Call_Prepend (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<function at remote 0x7ffff7242e60>, 
    obj=obj@entry=<_HookCaller(name='pytest_cmdline_main', _wrappers=[], _nonwrappers=[<HookImpl(function=<function at remote 0x7ffff6b61440>, argnames=('config',), kwargnames=(), plugin=<module at remote 0x7ffff6dd0050>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': False, 'hookwrapper': False, 'specname': None}, plugin_name='main', tryfirst=False, trylast=False, optionalhook=False, hookwrapper=False, specname=None) at remote 0x7ffff68ba810>, <HookImpl(function=<function at remote 0x7ffff68a9230>, argnames=('config',), kwargnames=(...), plugin=<module at remote 0x7ffff68c3d70>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': False, 'hookwrapper': False, 'specname': None}, plugin_name='helpconfig', tryfirst=False, trylast=False, optionalhook=False, hookwrapper=False, specname=None) at remote 0x7ffff68c4b50>, <HookImpl(function=<function at remote 0x7ffff6b77e30>, argnames=('config',), kwargnames=(...), plugin=<module at remote 0x7ffff6b7ddf0>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': F...(truncated), args=args@entry=(), 
    kwargs=kwargs@entry={'config': <Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, lsof=False, runpytest='inprocess', markers=False, usepdb=False, usepdb_cls=None, trace=False, lf=False, failedfirst=False, newfirst...(truncated)) at Objects/call.c:482
#84 0x0000555555739abc in slot_tp_call (
    self=<_HookCaller(name='pytest_cmdline_main', _wrappers=[], _nonwrappers=[<HookImpl(function=<function at remote 0x7ffff6b61440>, argnames=('config',), kwargnames=(), plugin=<module at remote 0x7ffff6dd0050>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': False, 'hookwrapper': False, 'specname': None}, plugin_name='main', tryfirst=False, trylast=False, optionalhook=False, hookwrapper=False, specname=None) at remote 0x7ffff68ba810>, <HookImpl(function=<function at remote 0x7ffff68a9230>, argnames=('config',), kwargnames=(...), plugin=<module at remote 0x7ffff68c3d70>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': False, 'hookwrapper': False, 'specname': None}, plugin_name='helpconfig', tryfirst=False, trylast=False, optionalhook=False, hookwrapper=False, specname=None) at remote 0x7ffff68c4b50>, <HookImpl(function=<function at remote 0x7ffff6b77e30>, argnames=('config',), kwargnames=(...), plugin=<module at remote 0x7ffff6b7ddf0>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': F...(truncated), args=(), 
    kwds={'config': <Config(option=<Namespace(keyword='', markexpr='', maxfail=0, continue_on_collection_errors=False, confcutdir=None, noconftest=False, keepduplicates=False, collect_in_virtualenv=False, importmode='prepend', basetemp=None, durations=None, durations_min=<float at remote 0x7ffff7792500>, version=0, plugins=['pytester'], traceconfig=False, showfixtures=False, show_fixtures_per_test=False, verbose=0, no_header=False, no_summary=False, reportchars='fEX', disable_warnings=False, showlocals=False, tbstyle='auto', showcapture='all', fulltrace=False, color='auto', code_highlight='yes', capture='fd', runxfail=False, pastebin=None, assertmode='rewrite', xmlpath=None, junitprefix=None, doctestmodules=False, doctestreport='udiff', doctestglob=[], doctest_ignore_import_errors=False, doctest_continue_on_failure=False, last_failed_no_failures='all', stepwise=False, stepwise_skip=False, lsof=False, runpytest='inprocess', markers=False, usepdb=False, usepdb_cls=None, trace=False, lf=False, failedfirst=False, newfirst...(truncated)) at Objects/typeobject.c:7598
#85 0x00005555556d03e3 in _PyObject_MakeTpCall (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, 
    callable=callable@entry=<_HookCaller(name='pytest_cmdline_main', _wrappers=[], _nonwrappers=[<HookImpl(function=<function at remote 0x7ffff6b61440>, argnames=('config',), kwargnames=(), plugin=<module at remote 0x7ffff6dd0050>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': False, 'hookwrapper': False, 'specname': None}, plugin_name='main', tryfirst=False, trylast=False, optionalhook=False, hookwrapper=False, specname=None) at remote 0x7ffff68ba810>, <HookImpl(function=<function at remote 0x7ffff68a9230>, argnames=('config',), kwargnames=(...), plugin=<module at remote 0x7ffff68c3d70>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': False, 'hookwrapper': False, 'specname': None}, plugin_name='helpconfig', tryfirst=False, trylast=False, optionalhook=False, hookwrapper=False, specname=None) at remote 0x7ffff68c4b50>, <HookImpl(function=<function at remote 0x7ffff6b77e30>, argnames=('config',), kwargnames=(...), plugin=<module at remote 0x7ffff6b7ddf0>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': F...(truncated), args=args@entry=0x7ffff7e6c358, nargs=<optimized out>, keywords=keywords@entry=('config',)) at Objects/call.c:214
#86 0x00005555556d061f in _PyObject_VectorcallTstate (tstate=0x555555b2f5e8 <_PyRuntime+166312>, 
    callable=callable@entry=<_HookCaller(name='pytest_cmdline_main', _wrappers=[], _nonwrappers=[<HookImpl(function=<function at remote 0x7ffff6b61440>, argnames=('config',), kwargnames=(), plugin=<module at remote 0x7ffff6dd0050>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': False, 'hookwrapper': False, 'specname': None}, plugin_name='main', tryfirst=False, trylast=False, optionalhook=False, hookwrapper=False, specname=None) at remote 0x7ffff68ba810>, <HookImpl(function=<function at remote 0x7ffff68a9230>, argnames=('config',), kwargnames=(...), plugin=<module at remote 0x7ffff68c3d70>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': False, 'hookwrapper': False, 'specname': None}, plugin_name='helpconfig', tryfirst=False, trylast=False, optionalhook=False, hookwrapper=False, specname=None) at remote 0x7ffff68c4b50>, <HookImpl(function=<function at remote 0x7ffff6b77e30>, argnames=('config',), kwargnames=(...), plugin=<module at remote 0x7ffff6b7ddf0>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': F...(truncated), args=args@entry=0x7ffff7e6c358, nargsf=<optimized out>, kwnames=kwnames@entry=('config',)) at ./Include/internal/pycore_call.h:90
#87 0x00005555556d0676 in PyObject_Vectorcall (
    callable=callable@entry=<_HookCaller(name='pytest_cmdline_main', _wrappers=[], _nonwrappers=[<HookImpl(function=<function at remote 0x7ffff6b61440>, argnames=('config',), kwargnames=(), plugin=<module at remote 0x7ffff6dd0050>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': False, 'hookwrapper': False, 'specname': None}, plugin_name='main', tryfirst=False, trylast=False, optionalhook=False, hookwrapper=False, specname=None) at remote 0x7ffff68ba810>, <HookImpl(function=<function at remote 0x7ffff68a9230>, argnames=('config',), kwargnames=(...), plugin=<module at remote 0x7ffff68c3d70>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': False, 'hookwrapper': False, 'specname': None}, plugin_name='helpconfig', tryfirst=False, trylast=False, optionalhook=False, hookwrapper=False, specname=None) at remote 0x7ffff68c4b50>, <HookImpl(function=<function at remote 0x7ffff6b77e30>, argnames=('config',), kwargnames=(...), plugin=<module at remote 0x7ffff6b7ddf0>, opts={'tryfirst': False, 'trylast': False, 'optionalhook': F...(truncated), args=args@entry=0x7ffff7e6c358, nargsf=<optimized out>, kwnames=kwnames@entry=('config',)) at Objects/call.c:299
#88 0x00005555557b8fef in _PyEval_EvalFrameDefault (tstate=0x555555b2f5e8 <_PyRuntime+166312>, frame=0x7ffff7e6c2a8, throwflag=<optimized out>) at Python/ceval.c:4773
#89 0x00005555557bd6cd in _PyEval_EvalFrame (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, frame=frame@entry=0x7ffff7e6c1b8, throwflag=throwflag@entry=0) at ./Include/internal/pycore_ceval.h:72
#90 0x00005555557bd7ce in _PyEval_Vector (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, func=func@entry=0x7ffff7681b20, 
    locals=locals@entry={'__name__': '__main__', '__doc__': 'The pytest entry point.', '__package__': 'pytest', '__loader__': <SourceFileLoader(name='pytest.__main__', path='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py') at remote 0x7ffff6aa67c0>, '__spec__': <ModuleSpec(name='pytest.__main__', loader=<...>, origin='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py', loader_state=None, submodule_search_locations=None, _uninitialized_submodules=[], _set_fileattr=True, _cached='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__pycache__/__main__.cpython-311.pyc') at remote 0x7ffff75161d0>, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff779f1d0>, '__file__': '/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py', '__cached__': '/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__pycache__/__main__.cpython-311.pyc', 'pytest': <module at remote 0x7ffff7518890>}, args=args@entry=0x0, argcount=argcount@entry=0, kwnames=kwnames@entry=0x0) at Python/ceval.c:6421
#91 0x00005555557bd8e3 in PyEval_EvalCode (co=co@entry=<code at remote 0x7ffff6a679a0>, 
    globals=globals@entry={'__name__': '__main__', '__doc__': 'The pytest entry point.', '__package__': 'pytest', '__loader__': <SourceFileLoader(name='pytest.__main__', path='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py') at remote 0x7ffff6aa67c0>, '__spec__': <ModuleSpec(name='pytest.__main__', loader=<...>, origin='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py', loader_state=None, submodule_search_locations=None, _uninitialized_submodules=[], _set_fileattr=True, _cached='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__pycache__/__main__.cpython-311.pyc') at remote 0x7ffff75161d0>, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff779f1d0>, '__file__': '/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py', '__cached__': '/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__pycache__/__main__.cpython-311.pyc', 'pytest': <module at remote 0x7ffff7518890>}, 
    locals=locals@entry={'__name__': '__main__', '__doc__': 'The pytest entry point.', '__package__': 'pytest', '__loader__': <SourceFileLoader(name='pytest.__main__', path='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py') at remote 0x7ffff6aa67c0>, '__spec__': <ModuleSpec(name='pytest.__main__', loader=<...>, origin='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py', loader_state=None, submodule_search_locations=None, _uninitialized_submodules=[], _set_fileattr=True, _cached='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__pycache__/__main__.cpython-311.pyc') at remote 0x7ffff75161d0>, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff779f1d0>, '__file__': '/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py', '__cached__': '/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__pycache__/__main__.cpython-311.pyc', 'pytest': <module at remote 0x7ffff7518890>}) at Python/ceval.c:1155
#92 0x00005555557a459b in builtin_exec_impl (module=module@entry=<module at remote 0x7ffff779f1d0>, source=<code at remote 0x7ffff6a679a0>, 
    globals={'__name__': '__main__', '__doc__': 'The pytest entry point.', '__package__': 'pytest', '__loader__': <SourceFileLoader(name='pytest.__main__', path='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py') at remote 0x7ffff6aa67c0>, '__spec__': <ModuleSpec(name='pytest.__main__', loader=<...>, origin='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py', loader_state=None, submodule_search_locations=None, _uninitialized_submodules=[], _set_fileattr=True, _cached='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__pycache__/__main__.cpython-311.pyc') at remote 0x7ffff75161d0>, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff779f1d0>, '__file__': '/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py', '__cached__': '/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__pycache__/__main__.cpython-311.pyc', 'pytest': <module at remote 0x7ffff7518890>}, 
    locals={'__name__': '__main__', '__doc__': 'The pytest entry point.', '__package__': 'pytest', '__loader__': <SourceFileLoader(name='pytest.__main__', path='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py') at remote 0x7ffff6aa67c0>, '__spec__': <ModuleSpec(name='pytest.__main__', loader=<...>, origin='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py', loader_state=None, submodule_search_locations=None, _uninitialized_submodules=[], _set_fileattr=True, _cached='/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__pycache__/__main__.cpython-311.pyc') at remote 0x7ffff75161d0>, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff779f1d0>, '__file__': '/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__main__.py', '__cached__': '/home/florian/tmp/python-pytest/.venv/lib/python3.11/site-packages/pytest/__pycache__/__main__.cpython-311.pyc', 'pytest': <module at remote 0x7ffff7518890>}, closure=0x0) at Python/bltinmodule.c:1075
#93 0x00005555557a46b4 in builtin_exec (module=<module at remote 0x7ffff779f1d0>, args=<optimized out>, args@entry=0x7ffff7e6c180, nargs=nargs@entry=2, kwnames=kwnames@entry=0x0) at Python/clinic/bltinmodule.c.h:465
#94 0x0000555555717156 in cfunction_vectorcall_FASTCALL_KEYWORDS (func=<built-in method exec of module object at remote 0x7ffff779f1d0>, args=0x7ffff7e6c180, nargsf=<optimized out>, kwnames=0x0) at Objects/methodobject.c:443
#95 0x00005555556d059f in _PyObject_VectorcallTstate (tstate=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<built-in method exec of module object at remote 0x7ffff779f1d0>, args=args@entry=0x7ffff7e6c180, nargsf=9223372036854775810, kwnames=kwnames@entry=0x0) at ./Include/internal/pycore_call.h:92
#96 0x00005555556d0676 in PyObject_Vectorcall (callable=callable@entry=<built-in method exec of module object at remote 0x7ffff779f1d0>, args=args@entry=0x7ffff7e6c180, nargsf=<optimized out>, kwnames=kwnames@entry=0x0) at Objects/call.c:299
#97 0x00005555557b8fef in _PyEval_EvalFrameDefault (tstate=0x555555b2f5e8 <_PyRuntime+166312>, frame=0x7ffff7e6c0d8, throwflag=<optimized out>) at Python/ceval.c:4773
#98 0x00005555557bd6cd in _PyEval_EvalFrame (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, frame=frame@entry=0x7ffff7e6c020, throwflag=throwflag@entry=0) at ./Include/internal/pycore_ceval.h:72
#99 0x00005555557bd7ce in _PyEval_Vector (tstate=0x555555b2f5e8 <_PyRuntime+166312>, func=0x7ffff751eaf0, locals=locals@entry=0x0, args=0x7ffff7689418, argcount=<optimized out>, kwnames=0x0) at Python/ceval.c:6421
#100 0x00005555556d023e in _PyFunction_Vectorcall (func=<optimized out>, stack=<optimized out>, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/call.c:393
#101 0x00005555556cfde3 in _PyVectorcall_Call (tstate=tstate@entry=0x555555b2f5e8 <_PyRuntime+166312>, func=0x5555556d01ee <_PyFunction_Vectorcall>, callable=callable@entry=<function at remote 0x7ffff751eaf0>, tuple=tuple@entry=('pytest', True), kwargs=kwargs@entry=0x0) at Objects/call.c:245
#102 0x00005555556d0180 in _PyObject_Call (tstate=0x555555b2f5e8 <_PyRuntime+166312>, callable=callable@entry=<function at remote 0x7ffff751eaf0>, args=args@entry=('pytest', True), kwargs=kwargs@entry=0x0) at Objects/call.c:328
#103 0x00005555556d01c8 in PyObject_Call (callable=callable@entry=<function at remote 0x7ffff751eaf0>, args=args@entry=('pytest', True), kwargs=kwargs@entry=0x0) at Objects/call.c:355
#104 0x00005555558223fe in pymain_run_module (modname=<optimized out>, set_argv0=set_argv0@entry=1) at Modules/main.c:300
#105 0x0000555555822edf in pymain_run_python (exitcode=exitcode@entry=0x7fffffffcae4) at Modules/main.c:595
#106 0x000055555582316e in Py_RunMain () at Modules/main.c:680
#107 0x00005555558231e8 in pymain_main (args=args@entry=0x7fffffffcb40) at Modules/main.c:710
#108 0x00005555558232b7 in Py_BytesMain (argc=<optimized out>, argv=<optimized out>) at Modules/main.c:734
#109 0x0000555555644732 in main (argc=<optimized out>, argv=<optimized out>) at ./Programs/python.c:15

Your environment

  • CPython versions tested on: Current 3.11 branch (cb4359c and df091e1)
  • Operating system and architecture: Archlinux x86_64
@pablogsal
Copy link
Member

Is possible that this is just that the assertion here fails because the node was not created by us, but this could corrupt the line table info (I need to check, maybe we are handling values of -1 correctly).

@pablogsal
Copy link
Member

I will take a look this weekend

@AlexWaygood AlexWaygood added the 3.11 only security fixes label Jul 8, 2022
@iritkatriel
Copy link
Member

I'm not getting that assertion, I'm getting something that looks like a GC crash:

platform darwin -- Python 3.11.0b3+, pytest-7.2.0.dev196+g966d4fb3e, pluggy-1.0.0
rootdir: /Users/iritkatriel/src/pytest, configfile: pyproject.toml, testpaths: testing
plugins: hypothesis-6.49.1
collecting ... Fatal Python error: Aborted

Current thread 0x000000011a8a3600 (most recent call first):
  File "/Users/iritkatriel/src/pytest/src/_pytest/assertion/rewrite.py", line 361 in _rewrite_test
  File "/Users/iritkatriel/src/pytest/src/_pytest/assertion/rewrite.py", line 159 in exec_module
  File "<frozen importlib._bootstrap>", line 690 in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1149 in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1178 in _find_and_load
  File "<frozen importlib._bootstrap>", line 1206 in _gcd_import
  File "/Users/iritkatriel/src/cpython/Lib/importlib/__init__.py", line 126 in import_module
  File "/Users/iritkatriel/src/pytest/src/_pytest/pathlib.py", line 533 in import_path
  File "/Users/iritkatriel/src/pytest/src/_pytest/python.py", line 617 in _importtestmodule
  File "/Users/iritkatriel/src/pytest/src/_pytest/python.py", line 528 in _getobj
  File "/Users/iritkatriel/src/pytest/src/_pytest/python.py", line 310 in obj
  File "/Users/iritkatriel/src/pytest/src/_pytest/python.py", line 545 in _inject_setup_module_fixture
  File "/Users/iritkatriel/src/pytest/src/_pytest/python.py", line 531 in collect
  File "/Users/iritkatriel/src/pytest/src/_pytest/runner.py", line 370 in <lambda>
  File "/Users/iritkatriel/src/pytest/src/_pytest/runner.py", line 339 in from_call
  File "/Users/iritkatriel/src/pytest/src/_pytest/runner.py", line 370 in pytest_make_collect_report
  File "/Users/iritkatriel/src/pytest/.venv/lib/python3.11/site-packages/pluggy/_callers.py", line 39 in _multicall
  File "/Users/iritkatriel/src/pytest/.venv/lib/python3.11/site-packages/pluggy/_manager.py", line 80 in _hookexec
  File "/Users/iritkatriel/src/pytest/.venv/lib/python3.11/site-packages/pluggy/_hooks.py", line 265 in __call__
  File "/Users/iritkatriel/src/pytest/src/_pytest/runner.py", line 538 in collect_one_node
  File "/Users/iritkatriel/src/pytest/src/_pytest/main.py", line 831 in genitems
  File "/Users/iritkatriel/src/pytest/src/_pytest/main.py", line 664 in perform_collect
  File "/Users/iritkatriel/src/pytest/src/_pytest/main.py", line 334 in pytest_collection
  File "/Users/iritkatriel/src/pytest/.venv/lib/python3.11/site-packages/pluggy/_callers.py", line 39 in _multicall
  File "/Users/iritkatriel/src/pytest/.venv/lib/python3.11/site-packages/pluggy/_manager.py", line 80 in _hookexec
  File "/Users/iritkatriel/src/pytest/.venv/lib/python3.11/site-packages/pluggy/_hooks.py", line 265 in __call__
  File "/Users/iritkatriel/src/pytest/src/_pytest/main.py", line 323 in _main
  File "/Users/iritkatriel/src/pytest/src/_pytest/main.py", line 270 in wrap_session
  File "/Users/iritkatriel/src/pytest/src/_pytest/main.py", line 317 in pytest_cmdline_main
  File "/Users/iritkatriel/src/pytest/.venv/lib/python3.11/site-packages/pluggy/_callers.py", line 39 in _multicall
  File "/Users/iritkatriel/src/pytest/.venv/lib/python3.11/site-packages/pluggy/_manager.py", line 80 in _hookexec
  File "/Users/iritkatriel/src/pytest/.venv/lib/python3.11/site-packages/pluggy/_hooks.py", line 265 in __call__
  File "/Users/iritkatriel/src/pytest/src/_pytest/config/__init__.py", line 165 in main
  File "/Users/iritkatriel/src/pytest/src/_pytest/config/__init__.py", line 188 in console_main
  File "/Users/iritkatriel/src/pytest/.venv/bin/pytest", line 33 in <module>
zsh: abort      .venv/bin/pytest

@brandtbucher
Copy link
Member

brandtbucher commented Jul 8, 2022

@iritkatriel, I'm getting that too. But if you look at a core dump, you can see it's hitting that assertion. Maybe pytest is capturing the output during collection or something.

With a bit of debugging, I found that the assert is hit when Pytest is rewriting the following four Python-level assert statements:

Where I'm at now with this: removing 'end_lineno' and 'end_column_offset' from ast.copy_location fixes the problem, but I'm not sure why.

@brandtbucher
Copy link
Member

Also, make sure you're setting PYTHONDONTWRITEBYTECODE=1 when debugging this. Otherwise Pytest caches the bytecode of the rewritten files alongside the normal .pycs.

@iritkatriel
Copy link
Member

Those locations have negative start columns, surely that would mess things up. -1 is "no value", but -2 and -6 are not expected.

@brandtbucher
Copy link
Member

brandtbucher commented Jul 8, 2022

Yep. I'm just wondering how we get there. Pytest doesn't set any end_col_offset values when rewriting.

Theory: They're inserting method calls, but keeping the same location info as the old assert. This messes up update_location_to_match_attr, since it is going to try to subtract some longish attribute name from a short-ish end_col_offset. If so, we should just make sure that update_location_to_match_attr falls back on -1 or something if its calculation produces a negative value.

@brandtbucher
Copy link
Member

Yep, my hunch was correct. The following patch fixes this issue on the 3.11 branch:

diff --git a/Python/compile.c b/Python/compile.c
index a71e7d31ee..f14315748d 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -4790,6 +4790,9 @@ update_location_to_match_attr(struct compiler *c, expr_ty meth)
         // Make start location match attribute
         c->u->u_lineno = meth->end_lineno;
         c->u->u_col_offset = meth->end_col_offset - (int)PyUnicode_GetLength(meth->v.Attribute.attr)-1;
+        if (c->u->u_col_offset < -1) {
+            c->u->u_col_offset = -1;
+        }
     }
 }

@brandtbucher
Copy link
Member

So I'm willing to call this one "our fault", even though Pytest is doing some pretty weird stuff here. I'll prepare a PR.

@iritkatriel
Copy link
Member

I don't know if we want to leave u_end_col_offset != -1 when u_col_offset is -1.

Also, we can test for the scenario you're conjecturing - I think we would see
meth->end_col_offset - meth->col_offset != (int)PyUnicode_GetLength(meth->v.Attribute.attr)

@iritkatriel
Copy link
Member

ormeth->end_col_offset - meth->col_offset != (int)PyUnicode_GetLength(meth->v.Attribute.attr)-1

@iritkatriel
Copy link
Member

So with this patch pytest works:

update_location_to_match_attr(struct compiler *c, expr_ty meth)
 {
     if (meth->lineno != meth->end_lineno) {
+      if (meth->end_col_offset - meth->col_offset == (int)PyUnicode_GetLength(meth->v.Attribute.attr)-1) {
         // Make start location match attribute
         c->u->u_lineno = meth->end_lineno;
         c->u->u_col_offset = meth->end_col_offset - (int)PyUnicode_GetLength(meth->v.Attribute.attr)-1;
+      }
     }
 }

@iritkatriel
Copy link
Member

But I don't think that's correct - probably in the case that someone messed up the AST we do want to unset the location as you did.

@brandtbucher
Copy link
Member

That breaks PEP 626 though. The whole point of update_location_to_match_attr is for the line number for the LOAD_ATTR or LOAD_METHOD to be the same as the attribute name's line number. Your patch no longer does that in this case.

@brandtbucher
Copy link
Member

This function was only intended for line numbers. When extended position info was added, it basically became a mostly-but-not-always-working hack for those too.

@iritkatriel
Copy link
Member

That function was added about 3 weeks ago. before that just line number was set, but that caused problems when a multiline function call had start_col > end_col. So this function tries to set the columns to something sensible.

Yeah, I know my patch is not the solution. The point of my patch is to confirm that the issue is due to a mismatch between the columns and the attr name in the AST.

(meth->end_col_offset - meth->col_offset == (int)PyUnicode_GetLength(meth->v.Attribute.attr)-1) is an invariant that should hold for an AST which is not malformed.

@iritkatriel
Copy link
Member

As for the solution - I would say that if someone dynamically rewrote the function name then there is no source location (the name is not in the source code at all). So we can set both col_offset and end_col_offset to -1.

static void
update_location_to_match_attr(struct compiler *c, expr_ty meth)
{
    if (meth->lineno != meth->end_lineno) {
        // Make start location match attribute
        c->u->u_lineno = meth->end_lineno;
        int attr_len = PyUnicode_GetLength(meth->v.Attribute.attr);
        if (meth->end_col_offset - meth->col_offset == attr_len - 1) {
            c->u->u_col_offset = meth->end_col_offset - attr_len - 1;
        }
        else {
            c->u->u_col_offset = c->u->u_end_col_offset = -1;
        }
    }
}

@brandtbucher
Copy link
Member

brandtbucher commented Jul 8, 2022

(meth->end_col_offset - meth->col_offset == (int)PyUnicode_GetLength(meth->v.Attribute.attr)-1) is an invariant that should hold for an AST which is not malformed.

Do you mean +1 at the end there? Either way, I think something like…

(a.
b())

…breaks this invariant. The issue is that that we assume the dot is on the same line as the name, which is why we adjust by one. That’s not always true.

I agree that just setting them both to -1 in the weird cases is probably the best bet here.

@iritkatriel
Copy link
Member

I think the 1 is not for the dot, but because end_col is the actual index of the last column (so end-start is 1 less than the length).

@brandtbucher
Copy link
Member

I think the 1 is not for the dot, but because end_col is the actual index of the last column (so end-start is 1 less than the length).

I don't think end_col_offset is inclusive:

>>> print(ast.dump(ast.parse("a.b").body[0], include_attributes=True, indent=4))
Expr(
    value=Attribute(
        value=Name(
            id='a',
            ctx=Load(),
            lineno=1,
            col_offset=0,
            end_lineno=1,
            end_col_offset=1),
        attr='b',
        ctx=Load(),
        lineno=1,
        col_offset=0,
        end_lineno=1,
        end_col_offset=3),
    lineno=1,
    col_offset=0,
    end_lineno=1,
    end_col_offset=3)

At any rate, I'm not sure what meth->end_col_offset - meth->col_offset would even mean here. If we get to this point, they're on different lines, so they shouldn't have any relationship to each other.

col_offset may even be greater than end_col_offset for legal code like:

(          a
.b())

@brandtbucher
Copy link
Member

The current code subtracts 1 to include the dot in the span:

Traceback (most recent call last):
  File "/home/brandtbucher/cpython/test_columns.py", line 3, in f
    .foo())
    ^^^^
AttributeError: 'NoneType' object has no attribute 'foo'

But this looks strange when the dot is on another line:

Traceback (most recent call last):
  File "/home/brandtbucher/cpython/test_columns.py", line 6, in <module>
    foo()
   ^^^^
AttributeError: 'NoneType' object has no attribute 'foo'

Or elsewhere on the same line:

Traceback (most recent call last):
  File "/home/brandtbucher/cpython/test_columns.py", line 10, in <module>
    . foo()
     ^^^^
AttributeError: 'NoneType' object has no attribute 'foo'

I propose we don't try to include the dot. It's more trouble than it's worth.

@iritkatriel
Copy link
Member

iritkatriel commented Jul 9, 2022

I don't think end_col_offset is inclusive:

Oh, the end line number is inclusive.

Yeah I agree about the dot.

At any rate, I'm not sure what meth->end_col_offset - meth->col_offset would even mean here. If we get to this point, they're on different lines, so they shouldn't have any relationship to each other.

Sorry I meant to look at the columns of meth->v.Attribute rather than meth.

Unfortunately that spans the dot so yeah they can be on different lines. But I don't know if it's a deliberate choice to include the dot in the attr. If it didn't include the dot we could use the column fields instead of PyUnicode_GetLength(meth->v.Attribute.attr) and in this case they would point to the source location of the unmodified method name, which is what would be displayed in a traceback anyway.

For 3.11 something along the lines of your PR is probably all we can do.
For 3.12 we could perhaps reject ASTs which are not consistent with themselves.

@The-Compiler
Copy link
Contributor Author

So I'm willing to call this one "our fault", even though Pytest is doing some pretty weird stuff here.

FWIW, with my pytest maintainer hat on (though I've never really looked at the assertion rewriting code in detail): If you have suggestions on how pytest could keep the same functionality but make it a little bit less weird, I'd be all ears!

(Maybe one day someone will get around to writing a PEP to get some kind of language support for the kind of thing pytest does, which would make those shenanigans unnecessary - I think @RonnyPfannschmidt did look at that some while ago, but I'm not sure if anything ever got out of it.)

@brandtbucher
Copy link
Member

Removing release blocker status, but leaving the issue open as we may want to make attributes Name nodes in the AST to avoid more headaches like this in 3.12+.

@brandtbucher brandtbucher added 3.12 bugs and security fixes and removed release-blocker labels Jul 10, 2022
@AlexWaygood AlexWaygood removed the 3.11 only security fixes label Jul 10, 2022
@iritkatriel
Copy link
Member

If you have suggestions on how pytest could keep the same functionality but make it a little bit less weird, I'd be all ears!

For this particular issue, if you can make sure that you replace “assert״ by a name of the same length, you will avoid the code path where we wipe the column info.

@markshannon
Copy link
Member

This is a CPython bug IMO, pytest (and other tools like coconut, hy, etc) should be able to produce an AST with whatever locations it likes (as long as they are valid).

The problem is that the compiler is "correcting" the location information from the parser. We should perform that transformation in the parser.
Moving update_location_to_match_attr() or equivalent to the parser is the way to go, I think.
That way it is up to the code that generates the AST to decide on locations.

@pablogsal
Copy link
Member

Moving update_location_to_match_attr() or equivalent to the parser is the way to go, I think.
That way it is up to the code that generates the AST to decide on locations.

I think what you are proposing is what what we are discussing in the PR that @brandtbucher made: adding enough location information to properly identify the attributes. Otherwise I don't think I would be getting what you are proposing: this function only makes sense in the compiler because it's trying to inline a multi line call. The parser currently populates correctly as much as it can.

@markshannon
Copy link
Member

markshannon commented Jul 11, 2022

The parser currently populates correctly as much as it can.

If the compiler needs to adjust the locations, then they aren't "correct".
What is "correct" is a bit subjective, but the locations we currently give multi-line method calls seem reasonable.

What I am suggesting is that the parser sets the locations to whatever we deem to be the "correct" location.
It is the compiler's job to convert the AST it is given into code objects; it shouldn't have to adjust locations.

That way, the compiler won't mess up the locations assigned by pytest.

@pablogsal
Copy link
Member

Well, the produced AST is completely correct. There is nothing that the parser is doing incorrectly here as far as I know.

If I understand correctly, the compiler is trying to transform the AST and therefore needs to do some processing to the original nodes to figure out the correct final offsets.

But as you can imagine, this is the compiler responsibility as the original AST produced by the parser is fully consistent. We can change it if you want or we can add or modify information, but there is nothing Intrinsically in the parser that can be considered a bug.

@pablogsal
Copy link
Member

More context so this is clear: the parser produces a correct AST for a multi-line method call that involves attribute access. Then the compiler does a bunch of checks to rule out imported names, calls with many arguments and then it emits an inlined LOAD_METHOD. This optimization needs to put the location information in the original attribute and therefore needs to manipulate the column offsets and the line number. As the compiler here is inlining things and trying to be smart, this is the responsibility of the compiler, not the parser.

@RonnyPfannschmidt
Copy link

since pytest currently expands subexpression results into variables, even method load
would it perhaps help to change the pytest ast generator to use the walrus operator instead of splitting things up

@markshannon
Copy link
Member

@pablogsal
What do you mean by "correct"?
We want useful locations. If the locations are "correct" but not useful, then it is better to be "incorrect".

If the compiler has to change the locations, and the output from the compiler is correct, then the input must be "incorrect".

Why is adjusting the locations the compiler's responsibility?
It's job is to convert the AST to a code object. It is the job of the parser to fill in the locations, IMO.

This has nothing to do with optimisation. It is about providing useful location information for calls.

@pablogsal
Copy link
Member

pablogsal commented Jul 11, 2022

What do you mean by "correct"? We want useful locations. If the locations are "correct" but not useful, then it is better to be "incorrect".

Correct means that the locations correspond to the code that generates the nodes. In any case I don't think we should discuss the metaphysics of correctness here :)

If the compiler has to change the locations, and the output from the compiler is correct, then the input must be "incorrect".

Again, the compiler does this because the compiler tries to transform the AST on the fly and infer the new locations so the generated debug info makes sense.

Why is adjusting the locations the compiler's responsibility?

Because is the compiler the one doing the transformations to the original AST.

@iritkatriel
Copy link
Member

@markshannon The issue (as we all agreed last week) is that the parser currently doesn't create a Name node for the attribute. This is why the compiler ends up trying to guess the location of the attribute from the other location info in the AST. The fix that @pablogsal suggested for this is to add this Name node in the parser.

@pablogsal
Copy link
Member

Exactly, that's what I said in #94694 (comment). The sentence that started this conversation is that if @markshannon was not referring to the fact that the strings do not have location in the current AST, then I was not understanding what he was proposing.

@markshannon
Copy link
Member

Let me try and explain some more.

Take the following statement:

obj
.a()
.b()
.c()

It is better for the purposes of tracing, debugging and error messages to treat the calls to a, b, and c as being on lines 2, 3, and 4 respectively.
If the parser gives them all a location with a starting line of 1, then I would argue that we should modify the parser.
Even though the parser's locations are "correct", they aren't useful.

@iritkatriel
This doesn't just apply to method calls, consider

(
    a + b
)()

What should be the location of the call?
The call is on line 3, even though the parts of the callable are all on line 2.

Currently the PEG parser produces locations that span the full range of locations within the tree.
We should add a post-parsing step that converts these "spans" into useful locations.
The compiler should then preserve those locations when generating code.

It isn't just calls, either. It is more useful to have the location of a for statement spanning the for to the : than encompassing the whole body. Likewise for other block statements.

@pablogsal
Copy link
Member

pablogsal commented Jul 11, 2022

If the parser gives them all a location with a starting line of 1, then I would argue that we should modify the parser.

Given

(
obj
.a()
.b()
.c()
)

The parser gives the calls lines (2,3), (2,4) and (2,5). This is because as with other expressions like 1+2+3 the last binary operator spans all the line because the left operand is the result of 1+2. You can perfectly know that the call itself ends in line 3, 4 and 5 by checking the end line numbers.

With this example:

(
    a + b
)()

The call spans (2,3).

We should add a post-parsing step that converts these "spans" into useful locations.

I strongly disagree, the parser should end producing the final AST. The whole design is so no post-processing is needed. Adding post-processing makes everything much more complicated as it makes the final output of the parser not the final product. And we already know how complicated to maintain that is because that was ast.c with its million inconsistencies. We have worked hard so locations are automated. And that should remain like that. Whatever we do, must be done in the main parser pass.

@pablogsal
Copy link
Member

pablogsal commented Jul 11, 2022

Currently the PEG parser produces locations that span the full range of locations within the tree.
We should add a post-parsing step that converts these "spans" into useful locations.
The compiler should then preserve those locations when generating code.

The parser produces nodes that spans the subtree. If you want the location of individual pieces in that node then you should visit the tree and get them, not mutating the tree based on the idiosyncratic nature of the receiver. The compiler is not the only consumer of this tree and what is useful for it may be super inconvenient for other consumers. And that's without considering how difficult and unmaintainable is going to be introducing manual location preferences into the machinery.

@markshannon
Copy link
Member

@pablogsal
What do you mean by "the idiosyncratic nature of the receiver"?

That the compiler is not the only consumer of the AST is even more reason to produce locations that are useful.
There is no reason why a type-checker presenting an error message would want spans rather than the more human understandable locations.

This is not about what is "convenient" for the compiler, but what are sensible locations for various AST nodes.
The compiler's job is to encode these locations, not to modify them.

Changing the locations post-parsing is a matter of walking the tree. Why would that be so difficult and unmaintainable?

@pablogsal
Copy link
Member

pablogsal commented Jul 11, 2022

What do you mean by "the idiosyncratic nature of the receiver"?

That what you define as "useful" here may not be for other consumers. AST analysis tools have been relying for years on the fact that the AST produced by the parser spans the entire subtree in every node. That was the design and that keeps being the design. In this particular case, the compiler is interested on assigning the location of a method call to the last attribute access and the parentheses, instead of the whole expression on the left hand side. But that is the preference of the compiler and may not be the same for other tools that want to do something different. You cannot just define "usefulness" by what you want the compiler to do. And here we already have a status quo that you would be breaking if we change how these nodes are defined.

A call in the parser is defined as

primary '(' [arguments] ')'

The parser doesn't know what is in primary and it cannot know. Therefore the AST node here spans the whole construct. What you want is alter the Call node based on what is inside primary. So the location will be different if is (a+b)(), a.b(), a[b]() .... And there are ton of edge cases. For example, what would you assign to the span of this?

(a
   + 
       b)(

)

I am arguing that that's not what the parser should do. The compiler should see the Call node, inspect what is inside primary and then decide what it wants to use to assign the position of the bytecode that is going to emit. In the current case, it wants to emit a LOAD_METHOD so it needs to check the span of the attribute access that's inside primary.

Changing the locations post-parsing is a matter of walking the tree. Why would that be so difficult and unmaintainable?

  • That the locations used by the compiler will not be the locations in the AST. So a tool like a debugger or alternate compiler or similar trying to match those will be very surprised when it knows that the AST was mutated in an intermediate step.
  • The locations in the AST are predictable and well-defined (in the sense that every tree spans its subtree and the span of the nodes is derived from the span of the tokens). All of this is automatic. When we introduced this we fixed all the tiny discrepancies and errors in the AST that existed before. What you propose re-introduces some manual adjustment and that has the potential to bring back all the tiny errors and discrepancies that happen when you have to manually propagate or fix the positions.

The correct thing to do here in my opinion is what we have discussed before and agreed with @iritkatriel and @brandtbucher. Make the parser to produce location for the NAME in the attribute access so the compiler can just pick it up and therefore it has nothing to fix. You can produce the bytecode you want for the cases you mentioned directly and no manual code is needed.

@markshannon
Copy link
Member

I agree that converting the right hand side of attributes to a NAME is the right thing to do.

I've opened #94758 to discuss the broader issue of what to do about locations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 bugs and security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-crash A hard crash of the interpreter, possibly with a core dump
Projects
Development

No branches or pull requests

7 participants