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 0You 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 0The 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


15r10nk commentedAug 12, 2022
•
edited
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: