diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_traceback.py b/graalpython/com.oracle.graal.python.test/src/tests/test_traceback.py index c045b20bf9..c412c3e780 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/test_traceback.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/test_traceback.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # The Universal Permissive License (UPL), Version 1.0 @@ -36,9 +36,8 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -import os +import ast import sys -import unittest def assert_raises(err, fn, *args, **kwargs): @@ -658,3 +657,14 @@ def test_faulthandler_many_threads(): if ids: ids_per_block.append(ids) assert len(ids) == 1, f"Interleaved output detected in block {header!r} with multiple thread func ids: {ids}" + + +def test_location_from_ast(): + m = compile("a = 1\nx", "", "exec", flags=ast.PyCF_ONLY_AST) + + try: + exec(compile(m, "", "exec")) + except NameError as e: + assert e.__traceback__.tb_next.tb_lineno == 2 + else: + assert False diff --git a/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_dictviews.txt b/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_dictviews.txt index 7f2f51d783..38e6fd21d9 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_dictviews.txt +++ b/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_dictviews.txt @@ -2,7 +2,8 @@ test.test_dictviews.DictSetTest.test_abc_registry @ darwin-arm64,linux-aarch64,l test.test_dictviews.DictSetTest.test_compare_error @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github test.test_dictviews.DictSetTest.test_constructors_not_callable @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github test.test_dictviews.DictSetTest.test_copy @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github -test.test_dictviews.DictSetTest.test_deeply_nested_repr @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,win32-AMD64,win32-AMD64-github +# Unreliable RecursionError +!test.test_dictviews.DictSetTest.test_deeply_nested_repr test.test_dictviews.DictSetTest.test_dict_items @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github test.test_dictviews.DictSetTest.test_dict_keys @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github test.test_dictviews.DictSetTest.test_dict_mixed_keys_items @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/compiler/bytecode_dsl/RootNodeCompiler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/compiler/bytecode_dsl/RootNodeCompiler.java index 9bebe538da..5ec45f3742 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/compiler/bytecode_dsl/RootNodeCompiler.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/compiler/bytecode_dsl/RootNodeCompiler.java @@ -788,20 +788,12 @@ boolean beginSourceSection(SourceRange sourceRange, Builder b) { SourceRange oldSourceRange = this.currentLocation; this.currentLocation = sourceRange; - if (ctx.source.hasCharacters()) { - int startOffset = getStartOffset(sourceRange); - int endOffset = getEndOffset(sourceRange); - int length = endOffset - startOffset; - if (length == 0) { - startOffset = 0; - } - b.beginSourceSection(startOffset, length); + beginSourceSectionInner(b, sourceRange); - if (oldSourceRange == null || oldSourceRange.startLine != sourceRange.startLine) { - b.beginTag(StatementTag.class); - b.beginBlock(); - return true; - } + if (oldSourceRange == null || oldSourceRange.startLine != sourceRange.startLine) { + b.beginTag(StatementTag.class); + b.beginBlock(); + return true; } return false; } @@ -820,39 +812,41 @@ void beginRootSourceSection(SSTNode node, Builder b) { sourceRange = node.getSourceRange(); } - if (ctx.source.hasCharacters()) { - int startOffset = getStartOffset(sourceRange); - int endOffset = getEndOffset(sourceRange); - int length = endOffset - startOffset; - if (length == 0) { - startOffset = 0; - } - b.beginSourceSection(startOffset, length); - } + beginSourceSectionInner(b, sourceRange); } - void endSourceSection(Builder b, boolean closeTag) { - if (ctx.source.hasCharacters()) { - if (closeTag) { - b.endBlock(); - b.endTag(StatementTag.class); + private static void beginSourceSectionInner(Builder b, SourceRange sourceRange) { + if (sourceRange.startLine >= 1) { + if (sourceRange.startColumn >= 0 && sourceRange.endLine >= sourceRange.startLine && sourceRange.endColumn >= 0) { + if (sourceRange.endColumn > 0) { + b.beginSourceSection(sourceRange.startLine, sourceRange.startColumn + 1, sourceRange.endLine, sourceRange.endColumn); + } else { + /* + * Truffle doesn't allow including an empty line with no characters, so we just + * include the first character to have at least something. It's not correct, but + * these cases are very rare, it occurs primarily in string consituents of + * top-level multiline format strings. + */ + b.beginSourceSection(sourceRange.startLine, sourceRange.startColumn + 1, sourceRange.endLine, 1); + } + } else { + b.beginSourceSection(sourceRange.startLine); } - b.endSourceSection(); + } else { + b.beginSourceSectionUnavailable(); } } - void endRootSourceSection(Builder b) { - if (ctx.source.hasCharacters()) { - b.endSourceSection(); + void endSourceSection(Builder b, boolean closeTag) { + if (closeTag) { + b.endBlock(); + b.endTag(StatementTag.class); } + b.endSourceSection(); } - int getStartOffset(SourceRange sourceRange) { - return ctx.source.getLineStartOffset(sourceRange.startLine) + sourceRange.startColumn; - } - - int getEndOffset(SourceRange sourceRange) { - return ctx.source.getLineStartOffset(sourceRange.endLine) + sourceRange.endColumn; + void endRootSourceSection(Builder b) { + b.endSourceSection(); } void beginReturn(Builder b) {