Skip to content

Commit 9cab133

Browse files
committed
[GR-12657] BaseException should allow set __traceback__.
PullRequest: graalpython/290
2 parents 3fff721 + ea4d958 commit 9cab133

File tree

4 files changed

+89
-7
lines changed

4 files changed

+89
-7
lines changed

graalpython/com.oracle.graal.python.test/src/graalpytest.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,15 @@ def assertSequenceEqual(self, expected, actual, msg=None):
158158
for expected_value in expected:
159159
assert expected_value == next(actual_iter), msg
160160

161+
def assertIsInstance(self, obj, cls, msg=None):
162+
"""Same as self.assertTrue(isinstance(obj, cls)), with a nicer
163+
default message."""
164+
if not isinstance(obj, cls):
165+
message = msg
166+
if msg is None:
167+
message = '%s is not an instance of %r' % (obj, cls)
168+
assert False, message
169+
161170
class assertRaises():
162171
def __init__(self, exc_type, function=None, *args, **kwargs):
163172
self.function = function
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Copyright (c) 2018, Oracle and/or its affiliates.
2+
# Copyright (C) 1996-2017 Python Software Foundation
3+
#
4+
# Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
5+
6+
import unittest
7+
import sys
8+
9+
class ExceptionTests(unittest.TestCase):
10+
11+
def testInvalidTraceback(self):
12+
try:
13+
Exception().__traceback__ = 5
14+
except TypeError as e:
15+
self.assertIn("__traceback__ must be a traceback", str(e))
16+
else:
17+
self.fail("No exception raised")
18+
19+
def testNoneClearsTracebackAttr(self):
20+
try:
21+
raise IndexError(4)
22+
except:
23+
tb = sys.exc_info()[2]
24+
25+
e = Exception()
26+
e.__traceback__ = tb
27+
e.__traceback__ = None
28+
self.assertEqual(e.__traceback__, None)
29+
30+
def testWithTraceback(self):
31+
try:
32+
raise IndexError(4)
33+
except:
34+
tb = sys.exc_info()[2]
35+
36+
e = BaseException().with_traceback(tb)
37+
self.assertIsInstance(e, BaseException)
38+
# TODO this dosn't work yet
39+
#self.assertEqual(e.__traceback__, tb)
40+
41+
e = IndexError(5).with_traceback(tb)
42+
self.assertIsInstance(e, IndexError)
43+
# TODO this dosn't work yet
44+
#self.assertEqual(e.__traceback__, tb)
45+
46+
class MyException(Exception):
47+
pass
48+
49+
e = MyException().with_traceback(tb)
50+
self.assertIsInstance(e, MyException)
51+
# TODO this dosn't work yet
52+
#self.assertEqual(e.__traceback__, tb)

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

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@
4949
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
5050
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
5151
import com.oracle.graal.python.nodes.object.GetLazyClassNode;
52+
import com.oracle.graal.python.runtime.exception.PythonErrorType;
5253
import com.oracle.graal.python.runtime.formatting.ErrorMessageFormatter;
5354
import com.oracle.truffle.api.CompilerDirectives;
5455
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
5556
import com.oracle.truffle.api.dsl.Cached;
57+
import com.oracle.truffle.api.dsl.Fallback;
5658
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
5759
import com.oracle.truffle.api.dsl.NodeFactory;
5860
import com.oracle.truffle.api.dsl.Specialization;
@@ -178,13 +180,31 @@ public boolean suppressContext(@SuppressWarnings("unused") PBaseException self)
178180
}
179181
}
180182

181-
@Builtin(name = __TRACEBACK__, fixedNumOfPositionalArgs = 1, isGetter = true)
183+
@Builtin(name = __TRACEBACK__, minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true)
182184
@GenerateNodeFactory
183185
public abstract static class TracebackNode extends PythonBuiltinNode {
184186

187+
@Specialization(guards = "isNoValue(tb)")
188+
public Object getTraceback(PBaseException self, @SuppressWarnings("unused") Object tb) {
189+
PTraceback traceback = self.getTraceback(factory());
190+
return traceback == null ? PNone.NONE : traceback;
191+
}
192+
185193
@Specialization
186-
public Object traceback(PBaseException self) {
187-
return self.getTraceback(factory());
194+
public Object setTraceback(PBaseException self, @SuppressWarnings("unused") PNone tb) {
195+
self.clearTraceback();
196+
return PNone.NONE;
197+
}
198+
199+
@Specialization
200+
public Object setTraceback(PBaseException self, PTraceback tb) {
201+
self.setTraceback(tb);
202+
return PNone.NONE;
203+
}
204+
205+
@Fallback
206+
public Object setTraceback(@SuppressWarnings("unused") Object self, @SuppressWarnings("unused") Object tb) {
207+
throw raise(PythonErrorType.TypeError, "__traceback__ must be a traceback or None");
188208
}
189209
}
190210

@@ -193,15 +213,15 @@ public Object traceback(PBaseException self) {
193213
public abstract static class WithTracebackNode extends PythonBuiltinNode {
194214

195215
@Specialization
196-
public Object withTraceback(PBaseException self, @SuppressWarnings("unused") PNone tb) {
216+
public PBaseException withTraceback(PBaseException self, @SuppressWarnings("unused") PNone tb) {
197217
self.clearTraceback();
198-
return PNone.NONE;
218+
return self;
199219
}
200220

201221
@Specialization
202-
public Object withTraceback(PBaseException self, PTraceback tb) {
222+
public PBaseException withTraceback(PBaseException self, PTraceback tb) {
203223
self.setTraceback(tb);
204-
return PNone.NONE;
224+
return self;
205225
}
206226
}
207227
}

mx.graalpython/copyrights/overrides

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ graalpython/com.oracle.graal.python.test/src/tests/test_compare.py,python.copyri
199199
graalpython/com.oracle.graal.python.test/src/tests/test_enumerate.py,python.copyright
200200
graalpython/com.oracle.graal.python.test/src/tests/test_euler11.py,benchmarks.copyright
201201
graalpython/com.oracle.graal.python.test/src/tests/test_euler31.py,benchmarks.copyright
202+
graalpython/com.oracle.graal.python.test/src/tests/test_exception.py,python.copyright
202203
graalpython/com.oracle.graal.python.test/src/tests/test_generator-accumulator.py,zippy.copyright
203204
graalpython/com.oracle.graal.python.test/src/tests/test_generator-continue.py,zippy.copyright
204205
graalpython/com.oracle.graal.python.test/src/tests/test_generator-expression-next.py,zippy.copyright

0 commit comments

Comments
 (0)