-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
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
comparison chaining has wrong source positions in most contexts (python 3.11.0rc2) #95921
Comments
…sert rewriting This affects also chained comparisons inside normal assertions because of python/cpython#95921. This is also the reason for the changes in sample results. once that is fixed we could revert the changes in the sample_results
@brandtbucher I think this is related to #93691. Does it makes sense for me to look into it? I have (almost) no cpython core developer experience and it would take me probably far longer than someone else. |
Thanks for the detailed report. This issue seems to stem from the fact that we have two implementations of comparisons in the bytecode compiler: one generic version ( I’ll have a fix up either today or tomorrow. It will probably need to wait for 3.11.1, though. |
…thonGH-96968). (cherry picked from commit dfc73b5) Co-authored-by: Brandt Bucher <brandtbucher@microsoft.com>
…thonGH-96968). (cherry picked from commit dfc73b5) Co-authored-by: Brandt Bucher <brandtbucher@microsoft.com>
…thonGH-96968). (cherry picked from commit dfc73b5) Co-authored-by: Brandt Bucher <brandtbucher@microsoft.com>
Thanks again for the great bug report! |
Big thank you for the quick bugfix @brandtbucher. But the fix caused another bug. The script: def func():
assert a and b<c , "msg"
import dis
for i in dis.get_instructions(func):
if i.opname in ("COMPARE_OP","CALL"):
print(i.positions,i.opname,i.argval) output (with your fix): Positions(lineno=4, end_lineno=4, col_offset=17, end_col_offset=20) COMPARE_OP <
Positions(lineno=4, end_lineno=4, col_offset=17, end_col_offset=20) CALL 0 You see that the positions of the output (the commit before your fix): Positions(lineno=4, end_lineno=4, col_offset=17, end_col_offset=20) COMPARE_OP <
Positions(lineno=4, end_lineno=4, col_offset=4, end_col_offset=28) CALL 0 The positions of the This did not cause any incorrect Tracebacks (at least I don't know how to produce it), but can cause problems for tools which analyse this positions. |
It is maybe also important that this is not the only example. assert b<c , "msg"
assert a<b<c , "msg"
assert a+b<c , "msg" show the same problems. I looks like everything with one or more |
Yep, I see the issue. My patch sets the location when recursing into the expression, but doesn't restore it after. |
…rsion 1.1.0 Alex Hall (4): GHA: test 3.11 and PRs Use `only` instead of `find_node` function Ignore EXTENDED_ARG/NOP when counting CALL_FUNCTION ops 3.11 in setup.cfg Frank Hoffmann (91): feat: support for python 3.11 fix: fixed decorator detection for 3.11.0a5 fix: detect decorators in 3.11.a6 correctly and ignore qualname checks for 3.11 feat: added support for more bytecodes and worked around some issues moved implementation for 3.11 to NewNodeFinder added missing sample_results file for 3.11 skip ast nodes in the which are related to annotations skip samples with incorrect syntax fixed some issues based on the current 3.11 branch wip: added _collections.py which leads to this bug python/cpython#95150 [skip ci] fix: fixed incompatibilities with master refactor: removed workaround for a fixed bug in python 3.11 fix: removed limitation in tests where the reason was fixed in cpython fix: uncommented test_module_files refactor: moved some code and renamed both NodeFinders perf: removed call of co_positions fix: removed code without meaning refactor: removed some ifs which where never true and improved documentation refactor: applied changes requested in review and simplified code refactor: added instruction() and opname() methods fix: STORE_ATTR with multiline fix: DELETE_ATTR with multiline fix: multiline method calls test: limited new tests to python 3.11 and added some more linebreaks refactor: do attribute lookups always without lineno col_offset attribute comparison test: call more things fix: do not return Assert nodes, because they are caused by pytest assert rewriting fix: this allowed the profiling with cProfile but let the python 2.7 tests fail if you run them twice feat: cache get_instructions result fix: always try to find a node with all positions (required for some edge cases) fix: workaround for python/cpython#95921 fix: EXTENDED_ARG is used for classes with lots of decorators fix: fixed some pattern matching related issues test: test with and listcomp fix: fix issues with master fix: handle assert-nodes as KnownIssue and limit the cases which can be fixed fix: handle exception cleanup for unmapped bytecodes fix: fix chain comparisons and report a KnownIssue if not possible fix: ignore pattern matching for now feat: implemented deadcode detection feat: implemented verifier test: improved tests refactor: extracted PositionNodeFinder into _position_node_finder.py refactor: used 3.11 syntax for _position_node_finder.py refactor: use lru_cache refactor: restructured special cases docu: explained __classcell__ issue refactor: splitted __init__ refactor: created is_except_cleanup staticmethod refactor: simplified inst_match refactor: created parents helper method refactor: improved and tested mangled_name refactor: unified verification for % string formatting refactor: unified verification for function call and class definition doc: added missing todo refactor: use Tester to test with statement refactor: moved and renamed start() and end() fix: not can be found in some cases fix: `is/is not None` can be found in some cases fix: removed duplicate code fix: fix `test_with` syntax for older python versions fix: specify python version fix: skip assert only for cpython 3.11 refactor: removed unnecessary try refactor: some cleanup in _position_node_finder.py fix: extended tests and also mangle ExceptHandler.name test: deleted redundant test fix: check correct deadcode annotation and fixed implementation fix: with statement fix: use is to compare with True/False fix: renamed _case to case_ fix: removed unused variables refactor: moved contains_break outside fix(deadcode): if condition is not dead based on the condition itself fix(verify): missing node for string concatenation fix: `while True:` can be broken by a `break` inside a `else:` block of a inner loop fix: __debug__ does not generate a LOAD instruction fix: some more `not ...` and `not x is x` do not generate instructions fix: classes where the mangeled names are in the bases do not count for name mangeling fix: not in `assert a if cnd else not b` can not be found, because it is part of the control flow fix: attribute gets not mangled if class name is `_` fix: tuples of literals are also literals fix: fixed bug in decorator detection fix: ExceptionHandler names can be mangled fix: also handle formatting cases like '%50s'%(a,) fix: `except TypeError as ValueError:` generated a STORE_GLOBAL fix: catch ValueError thrown by `ast.parse("\0")` fix: improved deadcode analysis build: moved test dependencies to setup.cfg test: extended test for multiline method calls fix: use previous non-CACHE instruction if f_lasti is a CACHE instruction
I have a working fix for 3.11 and 3.10, just need to write a decent regression test. I'll pick it back up tomorrow. |
can you please point me to the commit which fixes this issue. I would like to run the executing testsuite against it. |
Was going through older issues, looks like this is still an issue on 3.11. Brandt do you still have your branch? |
…sert rewriting This affects also chained comparisons inside normal assertions because of python/cpython#95921. This is also the reason for the changes in sample results. once that is fixed we could revert the changes in the sample_results
…sert rewriting This affects also chained comparisons inside normal assertions because of python/cpython#95921. This is also the reason for the changes in sample results. once that is fixed we could revert the changes in the sample_results
problem
comparison chaining has wrong source positions in most contexts
This bug requires two things to happen:
==
,in
,<=
,is
,...)no problem
The following examples work:
only one comparison
inside expression
reason
The problem seems to be the positions in the compiled bytecode:
script:
output (Python 3.11.0rc2+):
the generated ast looks fine (snippet):
other examples
here is a list of all the problems I found so far:
expected result
The positions should always match the ast-node range:
or, even better only the failing comparison:
The text was updated successfully, but these errors were encountered: