Skip to content

Commit 77d844a

Browse files
committed
[GR-48780] Implement exception notes
PullRequest: graalpython/3205
2 parents 70a4906 + c961b34 commit 77d844a

File tree

9 files changed

+82
-7
lines changed

9 files changed

+82
-7
lines changed

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_exception_group.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
*graalpython.lib-python.3.test.test_exception_group.NestedExceptionGroupBasicsTest.test_nested_group_chaining
3636
*graalpython.lib-python.3.test.test_exception_group.NestedExceptionGroupBasicsTest.test_nested_group_matches_template
3737
*graalpython.lib-python.3.test.test_exception_group.NestedExceptionGroupSplitTest.test_split_BaseExceptionGroup
38+
*graalpython.lib-python.3.test.test_exception_group.NestedExceptionGroupSplitTest.test_split_by_type
39+
*graalpython.lib-python.3.test.test_exception_group.NestedExceptionGroupSplitTest.test_split_copies_notes
3840
*graalpython.lib-python.3.test.test_exception_group.NestedExceptionGroupSplitTest.test_split_does_not_copy_non_sequence_notes
3941
*graalpython.lib-python.3.test.test_exception_group.NestedExceptionGroupSubclassSplitTest.test_split_BaseExceptionGroup_subclass_no_derive_new_override
4042
*graalpython.lib-python.3.test.test_exception_group.NestedExceptionGroupSubclassSplitTest.test_split_ExceptionGroup_subclass_derive_and_new_overrides

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_exceptions.txt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.testAttributes
77
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.testChainingAttrs
88
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.testChainingDescriptors
9-
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.testExceptionCleanupNames
109
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.testExceptionCleanupState
1110
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.testInvalidAttrs
1211
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.testInvalidTraceback
@@ -22,6 +21,7 @@
2221
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_MemoryError
2322
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_WindowsError
2423
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_assert_shadowing
24+
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_badisinstance
2525
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_context_of_exception_in_else_and_finally
2626
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_context_of_exception_in_except_and_finally
2727
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_context_of_exception_in_try_and_finally
@@ -46,12 +46,16 @@
4646
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_memory_error_cleanup
4747
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_memory_error_in_PyErr_PrintEx
4848
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_memory_error_subclasses
49+
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_no_hang_on_context_chain_cycle2
50+
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_notes
51+
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_raise_does_not_create_context_chain_cycle
4952
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_raise_in_generator
5053
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_recursion_error_cleanup
5154
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_recursion_normalizing_exception
5255
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_recursion_normalizing_infinite_exception
5356
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_recursion_normalizing_with_no_memory
5457
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_str
58+
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_trashcan_recursion
5559
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_unhandled
5660
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_unicode_change_attributes
5761
*graalpython.lib-python.3.test.test_exceptions.ExceptionTests.test_unicode_errors_no_object
@@ -62,3 +66,15 @@
6266
*graalpython.lib-python.3.test.test_exceptions.ImportErrorTests.test_copy_pickle
6367
*graalpython.lib-python.3.test.test_exceptions.ImportErrorTests.test_non_str_argument
6468
*graalpython.lib-python.3.test.test_exceptions.ImportErrorTests.test_reset_attributes
69+
*graalpython.lib-python.3.test.test_exceptions.NameErrorTests.test_issue45826
70+
*graalpython.lib-python.3.test.test_exceptions.NameErrorTests.test_issue45826_focused
71+
*graalpython.lib-python.3.test.test_exceptions.NameErrorTests.test_name_error_bad_suggestions_do_not_trigger_for_small_names
72+
*graalpython.lib-python.3.test.test_exceptions.NameErrorTests.test_name_error_suggestions_do_not_trigger_for_long_names
73+
*graalpython.lib-python.3.test.test_exceptions.NameErrorTests.test_name_error_suggestions_do_not_trigger_for_too_many_locals
74+
*graalpython.lib-python.3.test.test_exceptions.NameErrorTests.test_name_error_with_custom_exceptions
75+
*graalpython.lib-python.3.test.test_exceptions.NameErrorTests.test_unbound_local_error_doesn_not_match
76+
*graalpython.lib-python.3.test.test_exceptions.PEP626Tests.test_lineno_after_raise_in_with_exit
77+
*graalpython.lib-python.3.test.test_exceptions.PEP626Tests.test_lineno_after_raise_simple
78+
*graalpython.lib-python.3.test.test_exceptions.PEP626Tests.test_lineno_in_finally_normal
79+
*graalpython.lib-python.3.test.test_exceptions.PEP626Tests.test_lineno_in_try
80+
*graalpython.lib-python.3.test.test_exceptions.SyntaxErrorTests.test_attributes_old_constructor

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_traceback.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,14 @@
6969
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_exception_group_depth_limit
7070
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_exception_group_nested
7171
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_exception_group_width_limit
72+
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_exception_group_with_multiple_notes
73+
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_exception_group_with_notes
7274
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_exception_modulename
7375
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_exception_modulename_not_unicode
7476
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_exception_qualname
7577
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_exception_with_invalid_notes
78+
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_exception_with_multiple_notes
79+
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_exception_with_note
7680
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_message_none
7781
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_simple
7882
*graalpython.lib-python.3.test.test_traceback.PyExcReportingTests.test_syntax_error_no_lineno

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/BaseExceptionBuiltins.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2023, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2024, Oracle and/or its affiliates.
33
* Copyright (c) 2014, Regents of the University of California
44
*
55
* All rights reserved.
@@ -26,6 +26,7 @@
2626
package com.oracle.graal.python.builtins.objects.exception;
2727

2828
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
29+
import static com.oracle.graal.python.nodes.BuiltinNames.T___NOTES__;
2930
import static com.oracle.graal.python.nodes.ErrorMessages.P_TAKES_NO_KEYWORD_ARGS;
3031
import static com.oracle.graal.python.nodes.ErrorMessages.STATE_IS_NOT_A_DICT;
3132
import static com.oracle.graal.python.nodes.SpecialAttributeNames.J___CAUSE__;
@@ -68,12 +69,15 @@
6869
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
6970
import com.oracle.graal.python.lib.PyExceptionInstanceCheckNode;
7071
import com.oracle.graal.python.lib.PyObjectGetAttr;
72+
import com.oracle.graal.python.lib.PyObjectLookupAttr;
7173
import com.oracle.graal.python.lib.PyObjectReprAsTruffleStringNode;
7274
import com.oracle.graal.python.lib.PyObjectSetAttr;
7375
import com.oracle.graal.python.lib.PyObjectStrAsObjectNode;
76+
import com.oracle.graal.python.lib.PyUnicodeCheckNode;
7477
import com.oracle.graal.python.nodes.ErrorMessages;
7578
import com.oracle.graal.python.nodes.PGuards;
7679
import com.oracle.graal.python.nodes.PRaiseNode;
80+
import com.oracle.graal.python.nodes.builtins.ListNodes;
7781
import com.oracle.graal.python.nodes.expression.CastToListExpressionNode.CastToListNode;
7882
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
7983
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
@@ -520,4 +524,33 @@ static Object generic(@SuppressWarnings("unused") Object self, Object state,
520524
return PNone.NONE;
521525
}
522526
}
527+
528+
@Builtin(name = "add_note", minNumOfPositionalArgs = 2)
529+
@GenerateNodeFactory
530+
abstract static class AddNoteNode extends PythonBinaryBuiltinNode {
531+
@Specialization
532+
Object addNote(VirtualFrame frame, Object self, Object note,
533+
@Bind("this") Node inliningTarget,
534+
@Cached PyUnicodeCheckNode unicodeCheckNode,
535+
@Cached PyObjectLookupAttr lookupAttr,
536+
@Cached PyObjectSetAttr setAttr,
537+
@Cached ListNodes.AppendNode appendNode,
538+
@Cached PythonObjectFactory factory,
539+
@Cached PRaiseNode.Lazy raiseNode) {
540+
if (!unicodeCheckNode.execute(inliningTarget, note)) {
541+
throw raiseNode.get(inliningTarget).raise(TypeError, ErrorMessages.NOTE_MUST_BE_A_STR_NOT_P, note);
542+
}
543+
Object notes = lookupAttr.execute(frame, inliningTarget, self, T___NOTES__);
544+
if (notes == PNone.NO_VALUE) {
545+
notes = factory.createList();
546+
setAttr.execute(frame, inliningTarget, self, T___NOTES__, notes);
547+
}
548+
if (notes instanceof PList notesList) {
549+
appendNode.execute(notesList, note);
550+
} else {
551+
throw raiseNode.get(inliningTarget).raise(TypeError, ErrorMessages.CANNOT_ADD_NOTE_NOTES_IS_NOT_A_LIST);
552+
}
553+
return PNone.NONE;
554+
}
555+
}
523556
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/BaseExceptionGroupBuiltins.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import static com.oracle.graal.python.nodes.BuiltinNames.T_BUILTINS;
4444
import static com.oracle.graal.python.nodes.BuiltinNames.T_EXCEPTION_GROUP;
4545
import static com.oracle.graal.python.nodes.BuiltinNames.T_TYPE;
46+
import static com.oracle.graal.python.nodes.BuiltinNames.T___NOTES__;
4647
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___MODULE__;
4748
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___CLASS_GETITEM__;
4849
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___STR__;
@@ -63,16 +64,21 @@
6364
import com.oracle.graal.python.builtins.objects.common.EconomicMapStorage;
6465
import com.oracle.graal.python.builtins.objects.dict.PDict;
6566
import com.oracle.graal.python.builtins.objects.function.PFunction;
67+
import com.oracle.graal.python.builtins.objects.list.PList;
6668
import com.oracle.graal.python.builtins.objects.module.PythonModule;
6769
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
6870
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
6971
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
7072
import com.oracle.graal.python.lib.PyErrExceptionMatchesNode;
7173
import com.oracle.graal.python.lib.PyObjectCallMethodObjArgs;
7274
import com.oracle.graal.python.lib.PyObjectIsTrueNode;
75+
import com.oracle.graal.python.lib.PyObjectLookupAttr;
76+
import com.oracle.graal.python.lib.PyObjectSetAttr;
77+
import com.oracle.graal.python.lib.PySequenceCheckNode;
7378
import com.oracle.graal.python.lib.PyTupleCheckExactNode;
7479
import com.oracle.graal.python.nodes.ErrorMessages;
7580
import com.oracle.graal.python.nodes.PRaiseNode;
81+
import com.oracle.graal.python.nodes.builtins.ListNodes;
7682
import com.oracle.graal.python.nodes.call.CallNode;
7783
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
7884
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
@@ -194,7 +200,14 @@ private static PBaseExceptionGroup subset(Node inliningTarget, PBaseExceptionGro
194200
ExceptionNodes.SetContextNode.executeUncached(eg, context);
195201
Object cause = ExceptionNodes.GetCauseNode.executeUncached(orig);
196202
ExceptionNodes.SetCauseNode.executeUncached(eg, cause);
197-
// TODO copy notes
203+
Object notes = PyObjectLookupAttr.executeUncached(orig, T___NOTES__);
204+
if (notes != PNone.NO_VALUE) {
205+
if (PySequenceCheckNode.executeUncached(notes)) {
206+
/* Make a copy so the parts have independent notes lists. */
207+
PList notesCopy = ListNodes.ConstructListNode.getUncached().execute(null, notes);
208+
PyObjectSetAttr.executeUncached(eg, T___NOTES__, notesCopy);
209+
}
210+
}
198211
return eg;
199212
}
200213

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyObjectLookupAttr.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -92,8 +92,8 @@
9292
@GenerateCached
9393
@ImportStatic({SpecialMethodSlot.class, SpecialMethodNames.class, PGuards.class})
9494
public abstract class PyObjectLookupAttr extends Node {
95-
public static Object executeUncached(Object type, Object name) {
96-
return PyObjectLookupAttrNodeGen.getUncached().execute(null, null, type, name);
95+
public static Object executeUncached(Object receiver, Object name) {
96+
return PyObjectLookupAttrNodeGen.getUncached().execute(null, null, receiver, name);
9797
}
9898

9999
public final Object executeCached(Frame frame, Object receiver, Object name) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PySequenceCheckNode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@
7070
public abstract class PySequenceCheckNode extends PNodeWithContext {
7171
public abstract boolean execute(Node inliningTarget, Object object);
7272

73+
public static boolean executeUncached(Object object) {
74+
return PySequenceCheckNodeGen.getUncached().execute(null, object);
75+
}
76+
7377
@Specialization
7478
static boolean doSequence(@SuppressWarnings("unused") PSequence object) {
7579
return true;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/BuiltinNames.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ public abstract class BuiltinNames {
7070
public static final String J___DEBUG__ = "__debug__";
7171
public static final TruffleString T___DEBUG__ = tsLiteral(J___DEBUG__);
7272

73-
public static final String J___FUTURE__ = "__future__";
73+
public static final String J___NOTES__ = "__notes__";
74+
public static final TruffleString T___NOTES__ = tsLiteral(J___NOTES__);
7475

7576
// sys
7677
public static final TruffleString T_TRACEBACKLIMIT = tsLiteral("tracebacklimit");

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,4 +1612,6 @@ public abstract class ErrorMessages {
16121612
public static final TruffleString CANNOT_NEST_BASE_EXCEPTIONS_IN_N = tsLiteral("Cannot nest BaseExceptions in '%N'");
16131613
public static final TruffleString DERIVE_MUST_RETURN_AN_INSTANCE_OF_BASE_EXCEPTION_GROUP = tsLiteral("derive must return an instance of BaseExceptionGroup");
16141614
public static final TruffleString EXPECTED_A_FUNCTION_EXCEPTION_TYPE_OR_TUPLE_OF_EXCEPTION_TYPES = tsLiteral("expected a function, exception type or tuple of exception types");
1615+
public static final TruffleString NOTE_MUST_BE_A_STR_NOT_P = tsLiteral("note must be a str, not '%p'");
1616+
public static final TruffleString CANNOT_ADD_NOTE_NOTES_IS_NOT_A_LIST = tsLiteral("Cannot add note: __notes__ is not a list");
16151617
}

0 commit comments

Comments
 (0)