Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 828f04a

Browse files
committed
Issue #1066: implement PEP 3109, 2/3 of PEP 3134.
1 parent 150b7d7 commit 828f04a

32 files changed

Lines changed: 761 additions & 253 deletions

Grammar/Grammar

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ break_stmt: 'break'
4949
continue_stmt: 'continue'
5050
return_stmt: 'return' [testlist]
5151
yield_stmt: yield_expr
52-
raise_stmt: 'raise' [test [',' test [',' test]]]
52+
raise_stmt: 'raise' [test ['from' test]]
5353
import_stmt: import_name | import_from
5454
import_name: 'import' dotted_as_names
5555
# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS

Include/Python-ast.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,8 @@ struct _stmt {
134134
} With;
135135

136136
struct {
137-
expr_ty type;
138-
expr_ty inst;
139-
expr_ty tback;
137+
expr_ty exc;
138+
expr_ty cause;
140139
} Raise;
141140

142141
struct {
@@ -418,9 +417,9 @@ stmt_ty _Py_If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno,
418417
#define With(a0, a1, a2, a3, a4, a5) _Py_With(a0, a1, a2, a3, a4, a5)
419418
stmt_ty _Py_With(expr_ty context_expr, expr_ty optional_vars, asdl_seq * body,
420419
int lineno, int col_offset, PyArena *arena);
421-
#define Raise(a0, a1, a2, a3, a4, a5) _Py_Raise(a0, a1, a2, a3, a4, a5)
422-
stmt_ty _Py_Raise(expr_ty type, expr_ty inst, expr_ty tback, int lineno, int
423-
col_offset, PyArena *arena);
420+
#define Raise(a0, a1, a2, a3, a4) _Py_Raise(a0, a1, a2, a3, a4)
421+
stmt_ty _Py_Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset,
422+
PyArena *arena);
424423
#define TryExcept(a0, a1, a2, a3, a4, a5) _Py_TryExcept(a0, a1, a2, a3, a4, a5)
425424
stmt_ty _Py_TryExcept(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse,
426425
int lineno, int col_offset, PyArena *arena);

Include/pyerrors.h

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@ extern "C" {
66

77
/* Error objects */
88

9+
/* PyException_HEAD defines the initial segment of every exception class. */
10+
#define PyException_HEAD PyObject_HEAD; PyObject *dict;\
11+
PyObject *args; PyObject *traceback;\
12+
PyObject *context; PyObject *cause;
13+
914
typedef struct {
10-
PyObject_HEAD
11-
PyObject *dict;
12-
PyObject *args;
15+
PyException_HEAD
1316
} PyBaseExceptionObject;
1417

1518
typedef struct {
16-
PyObject_HEAD
17-
PyObject *dict;
18-
PyObject *args;
19+
PyException_HEAD
1920
PyObject *msg;
2021
PyObject *filename;
2122
PyObject *lineno;
@@ -25,9 +26,7 @@ typedef struct {
2526
} PySyntaxErrorObject;
2627

2728
typedef struct {
28-
PyObject_HEAD
29-
PyObject *dict;
30-
PyObject *args;
29+
PyException_HEAD
3130
PyObject *encoding;
3231
PyObject *object;
3332
Py_ssize_t start;
@@ -36,26 +35,20 @@ typedef struct {
3635
} PyUnicodeErrorObject;
3736

3837
typedef struct {
39-
PyObject_HEAD
40-
PyObject *dict;
41-
PyObject *args;
38+
PyException_HEAD
4239
PyObject *code;
4340
} PySystemExitObject;
4441

4542
typedef struct {
46-
PyObject_HEAD
47-
PyObject *dict;
48-
PyObject *args;
43+
PyException_HEAD
4944
PyObject *myerrno;
5045
PyObject *strerror;
5146
PyObject *filename;
5247
} PyEnvironmentErrorObject;
5348

5449
#ifdef MS_WINDOWS
5550
typedef struct {
56-
PyObject_HEAD
57-
PyObject *dict;
58-
PyObject *args;
51+
PyException_HEAD
5952
PyObject *myerrno;
6053
PyObject *strerror;
6154
PyObject *filename;
@@ -84,6 +77,19 @@ PyAPI_FUNC(int) PyErr_GivenExceptionMatches(PyObject *, PyObject *);
8477
PyAPI_FUNC(int) PyErr_ExceptionMatches(PyObject *);
8578
PyAPI_FUNC(void) PyErr_NormalizeException(PyObject**, PyObject**, PyObject**);
8679

80+
/* Traceback manipulation (PEP 3134) */
81+
PyAPI_FUNC(int) PyException_SetTraceback(PyObject *, PyObject *);
82+
PyAPI_FUNC(PyObject *) PyException_GetTraceback(PyObject *);
83+
84+
/* Cause manipulation (PEP 3134) */
85+
PyAPI_FUNC(PyObject *) PyException_GetCause(PyObject *);
86+
PyAPI_FUNC(void) PyException_SetCause(PyObject *, PyObject *);
87+
88+
/* Context manipulation (PEP 3134) */
89+
PyAPI_FUNC(PyObject *) PyException_GetContext(PyObject *);
90+
PyAPI_FUNC(void) PyException_SetContext(PyObject *, PyObject *);
91+
92+
8793
/* */
8894

8995
#define PyExceptionClass_Check(x) \
@@ -98,7 +104,7 @@ PyAPI_FUNC(void) PyErr_NormalizeException(PyObject**, PyObject**, PyObject**);
98104

99105
#define PyExceptionInstance_Class(x) ((PyObject*)((x)->ob_type))
100106

101-
107+
102108
/* Predefined exceptions */
103109

104110
PyAPI_DATA(PyObject *) PyExc_BaseException;
@@ -212,7 +218,7 @@ PyAPI_FUNC(void) PyErr_WriteUnraisable(PyObject *);
212218
PyAPI_FUNC(int) PyErr_WarnEx(PyObject *category, const char *msg,
213219
Py_ssize_t stack_level);
214220
PyAPI_FUNC(int) PyErr_WarnExplicit(PyObject *, const char *,
215-
const char *, int,
221+
const char *, int,
216222
const char *, PyObject *);
217223

218224
/* In sigcheck.c or signalmodule.c */

Lib/contextlib.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def nested(*managers):
125125
# Don't rely on sys.exc_info() still containing
126126
# the right information. Another exception may
127127
# have been raised and caught by an exit method
128-
raise exc[0], exc[1], exc[2]
128+
raise exc[0](exc[1]).with_traceback(exc[2])
129129

130130

131131
class closing(object):

Lib/doctest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,7 +1608,7 @@ class DebugRunner(DocTestRunner):
16081608
'42\n'
16091609
16101610
>>> exc_info = failure.exc_info
1611-
>>> raise exc_info[0], exc_info[1], exc_info[2]
1611+
>>> raise exc_info[1] # Already has the traceback
16121612
Traceback (most recent call last):
16131613
...
16141614
KeyError
@@ -2146,7 +2146,7 @@ def debug(self):
21462146
'42\n'
21472147
21482148
>>> exc_info = failure.exc_info
2149-
>>> raise exc_info[0], exc_info[1], exc_info[2]
2149+
>>> raise exc_info[1] # Already has the traceback
21502150
Traceback (most recent call last):
21512151
...
21522152
KeyError

Lib/os.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def _get_exports_list(module):
113113
del ce
114114

115115
else:
116-
raise ImportError, 'no os specific module found'
116+
raise ImportError('no os specific module found')
117117

118118
sys.modules['os.path'] = path
119119
from os.path import curdir, pardir, sep, pathsep, defpath, altsep, devnull
@@ -386,8 +386,8 @@ def _execvpe(file, args, env=None):
386386
saved_exc = e
387387
saved_tb = tb
388388
if saved_exc:
389-
raise error, saved_exc, saved_tb
390-
raise error, last_exc, tb
389+
raise error(saved_exc).with_traceback(saved_tb)
390+
raise error(last_exc).with_traceback(tb)
391391

392392

393393
# Change environ to automatically call putenv(), unsetenv if they exist.
@@ -492,7 +492,7 @@ def _spawnvef(mode, file, args, env, func):
492492
elif WIFEXITED(sts):
493493
return WEXITSTATUS(sts)
494494
else:
495-
raise error, "Not stopped, signaled or exited???"
495+
raise error("Not stopped, signaled or exited???")
496496

497497
def spawnv(mode, file, args):
498498
"""spawnv(mode, file, args) -> integer

Lib/test/test_ast.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def to_tuple(t):
3737
# If
3838
"if v:pass",
3939
# Raise
40-
"raise Exception, 'string'",
40+
"raise Exception('string')",
4141
# TryExcept
4242
"try:\n pass\nexcept Exception:\n pass",
4343
# TryFinally
@@ -160,7 +160,7 @@ def run_tests():
160160
('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])]),
161161
('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])]),
162162
('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])]),
163-
('Module', [('Raise', (1, 0), ('Name', (1, 6), 'Exception', ('Load',)), ('Str', (1, 17), 'string'), None)]),
163+
('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], [], None, None), None)]),
164164
('Module', [('TryExcept', (1, 0), [('Pass', (2, 2))], [('excepthandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))], 3, 0)], [])]),
165165
('Module', [('TryFinally', (1, 0), [('Pass', (2, 2))], [('Pass', (4, 2))])]),
166166
('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]),

Lib/test/test_exceptions.py

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class ExceptionTests(unittest.TestCase):
1313

1414
def raise_catch(self, exc, excname):
1515
try:
16-
raise exc, "spam"
16+
raise exc("spam")
1717
except exc as err:
1818
buf1 = str(err)
1919
try:
@@ -141,7 +141,7 @@ def testSettingException(self):
141141

142142
class BadException(Exception):
143143
def __init__(self_):
144-
raise RuntimeError, "can't instantiate BadException"
144+
raise RuntimeError("can't instantiate BadException")
145145

146146
class InvalidException:
147147
pass
@@ -305,6 +305,62 @@ def testAttributes(self):
305305
'pickled "%r", attribute "%s' %
306306
(e, checkArgName))
307307

308+
def testWithTraceback(self):
309+
try:
310+
raise IndexError(4)
311+
except:
312+
tb = sys.exc_info()[2]
313+
314+
e = BaseException().with_traceback(tb)
315+
self.failUnless(isinstance(e, BaseException))
316+
self.assertEqual(e.__traceback__, tb)
317+
318+
e = IndexError(5).with_traceback(tb)
319+
self.failUnless(isinstance(e, IndexError))
320+
self.assertEqual(e.__traceback__, tb)
321+
322+
class MyException(Exception):
323+
pass
324+
325+
e = MyException().with_traceback(tb)
326+
self.failUnless(isinstance(e, MyException))
327+
self.assertEqual(e.__traceback__, tb)
328+
329+
def testInvalidTraceback(self):
330+
try:
331+
Exception().__traceback__ = 5
332+
except TypeError as e:
333+
self.failUnless("__traceback__ must be a traceback" in str(e))
334+
else:
335+
self.fail("No exception raised")
336+
337+
def testNoneClearsTracebackAttr(self):
338+
try:
339+
raise IndexError(4)
340+
except:
341+
tb = sys.exc_info()[2]
342+
343+
e = Exception()
344+
e.__traceback__ = tb
345+
e.__traceback__ = None
346+
self.assertEqual(e.__traceback__, None)
347+
348+
def testChainingAttrs(self):
349+
e = Exception()
350+
self.assertEqual(e.__context__, None)
351+
self.assertEqual(e.__cause__, None)
352+
353+
e = TypeError()
354+
self.assertEqual(e.__context__, None)
355+
self.assertEqual(e.__cause__, None)
356+
357+
class MyException(EnvironmentError):
358+
pass
359+
360+
e = MyException()
361+
self.assertEqual(e.__context__, None)
362+
self.assertEqual(e.__cause__, None)
363+
308364
def testKeywordArgs(self):
309365
# test that builtin exception don't take keyword args,
310366
# but user-defined subclasses can if they want

Lib/test/test_grammar.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ def testYield(self):
438438

439439
def testRaise(self):
440440
# 'raise' test [',' test]
441-
try: raise RuntimeError, 'just testing'
441+
try: raise RuntimeError('just testing')
442442
except RuntimeError: pass
443443
try: raise KeyboardInterrupt
444444
except KeyboardInterrupt: pass

Lib/test/test_opcodes.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,10 @@ def __init__(self, ignore):
4646
a = AClass()
4747
b = BClass()
4848

49-
try: raise AClass, b
50-
except BClass as v:
51-
if v != b: self.fail("v!=b")
52-
else: self.fail("no exception")
53-
54-
try: raise b
49+
try:
50+
raise b
5551
except AClass as v:
56-
if v != b: self.fail("v!=b AClass")
52+
self.assertEqual(v, b)
5753
else:
5854
self.fail("no exception")
5955

@@ -62,7 +58,7 @@ def __init__(self, ignore):
6258
##except TypeError: pass
6359
##else: self.fail("no exception")
6460

65-
try: raise DClass, a
61+
try: raise DClass(a)
6662
except DClass as v:
6763
self.assert_(isinstance(v, DClass))
6864
else:

0 commit comments

Comments
 (0)