Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3.3
Changeset: r75197:41f2d5146ca3
Date: 2015-01-01 16:05 +0100
http://bitbucket.org/pypy/pypy/changeset/41f2d5146ca3/
Log: Implement CPython Issue #12199: The TryExcept and TryFinally and AST
nodes have been unified into a Try node.
diff --git a/pypy/interpreter/astcompiler/ast.py
b/pypy/interpreter/astcompiler/ast.py
--- a/pypy/interpreter/astcompiler/ast.py
+++ b/pypy/interpreter/astcompiler/ast.py
@@ -334,10 +334,8 @@
return With.from_object(space, w_node)
if space.isinstance_w(w_node, get(space).w_Raise):
return Raise.from_object(space, w_node)
- if space.isinstance_w(w_node, get(space).w_TryExcept):
- return TryExcept.from_object(space, w_node)
- if space.isinstance_w(w_node, get(space).w_TryFinally):
- return TryFinally.from_object(space, w_node)
+ if space.isinstance_w(w_node, get(space).w_Try):
+ return Try.from_object(space, w_node)
if space.isinstance_w(w_node, get(space).w_Assert):
return Assert.from_object(space, w_node)
if space.isinstance_w(w_node, get(space).w_Import):
@@ -1009,16 +1007,17 @@
State.ast_type('Raise', 'stmt', ['exc', 'cause'])
-class TryExcept(stmt):
-
- def __init__(self, body, handlers, orelse, lineno, col_offset):
+class Try(stmt):
+
+ def __init__(self, body, handlers, orelse, finalbody, lineno, col_offset):
self.body = body
self.handlers = handlers
self.orelse = orelse
+ self.finalbody = finalbody
stmt.__init__(self, lineno, col_offset)
def walkabout(self, visitor):
- visitor.visit_TryExcept(self)
+ visitor.visit_Try(self)
def mutate_over(self, visitor):
if self.body:
@@ -1027,10 +1026,12 @@
visitor._mutate_sequence(self.handlers)
if self.orelse:
visitor._mutate_sequence(self.orelse)
- return visitor.visit_TryExcept(self)
+ if self.finalbody:
+ visitor._mutate_sequence(self.finalbody)
+ return visitor.visit_Try(self)
def to_object(self, space):
- w_node = space.call_function(get(space).w_TryExcept)
+ w_node = space.call_function(get(space).w_Try)
if self.body is None:
body_w = []
else:
@@ -1049,57 +1050,6 @@
orelse_w = [node.to_object(space) for node in self.orelse] # stmt
w_orelse = space.newlist(orelse_w)
space.setattr(w_node, space.wrap('orelse'), w_orelse)
- w_lineno = space.wrap(self.lineno) # int
- space.setattr(w_node, space.wrap('lineno'), w_lineno)
- w_col_offset = space.wrap(self.col_offset) # int
- space.setattr(w_node, space.wrap('col_offset'), w_col_offset)
- return w_node
-
- @staticmethod
- def from_object(space, w_node):
- w_body = get_field(space, w_node, 'body', False)
- w_handlers = get_field(space, w_node, 'handlers', False)
- w_orelse = get_field(space, w_node, 'orelse', False)
- w_lineno = get_field(space, w_node, 'lineno', False)
- w_col_offset = get_field(space, w_node, 'col_offset', False)
- body_w = space.unpackiterable(w_body)
- _body = [stmt.from_object(space, w_item) for w_item in body_w]
- handlers_w = space.unpackiterable(w_handlers)
- _handlers = [excepthandler.from_object(space, w_item) for w_item in
handlers_w]
- orelse_w = space.unpackiterable(w_orelse)
- _orelse = [stmt.from_object(space, w_item) for w_item in orelse_w]
- _lineno = space.int_w(w_lineno)
- _col_offset = space.int_w(w_col_offset)
- return TryExcept(_body, _handlers, _orelse, _lineno, _col_offset)
-
-State.ast_type('TryExcept', 'stmt', ['body', 'handlers', 'orelse'])
-
-
-class TryFinally(stmt):
-
- def __init__(self, body, finalbody, lineno, col_offset):
- self.body = body
- self.finalbody = finalbody
- stmt.__init__(self, lineno, col_offset)
-
- def walkabout(self, visitor):
- visitor.visit_TryFinally(self)
-
- def mutate_over(self, visitor):
- if self.body:
- visitor._mutate_sequence(self.body)
- if self.finalbody:
- visitor._mutate_sequence(self.finalbody)
- return visitor.visit_TryFinally(self)
-
- def to_object(self, space):
- w_node = space.call_function(get(space).w_TryFinally)
- if self.body is None:
- body_w = []
- else:
- body_w = [node.to_object(space) for node in self.body] # stmt
- w_body = space.newlist(body_w)
- space.setattr(w_node, space.wrap('body'), w_body)
if self.finalbody is None:
finalbody_w = []
else:
@@ -1115,18 +1065,24 @@
@staticmethod
def from_object(space, w_node):
w_body = get_field(space, w_node, 'body', False)
+ w_handlers = get_field(space, w_node, 'handlers', False)
+ w_orelse = get_field(space, w_node, 'orelse', False)
w_finalbody = get_field(space, w_node, 'finalbody', False)
w_lineno = get_field(space, w_node, 'lineno', False)
w_col_offset = get_field(space, w_node, 'col_offset', False)
body_w = space.unpackiterable(w_body)
_body = [stmt.from_object(space, w_item) for w_item in body_w]
+ handlers_w = space.unpackiterable(w_handlers)
+ _handlers = [excepthandler.from_object(space, w_item) for w_item in
handlers_w]
+ orelse_w = space.unpackiterable(w_orelse)
+ _orelse = [stmt.from_object(space, w_item) for w_item in orelse_w]
finalbody_w = space.unpackiterable(w_finalbody)
_finalbody = [stmt.from_object(space, w_item) for w_item in
finalbody_w]
_lineno = space.int_w(w_lineno)
_col_offset = space.int_w(w_col_offset)
- return TryFinally(_body, _finalbody, _lineno, _col_offset)
-
-State.ast_type('TryFinally', 'stmt', ['body', 'finalbody'])
+ return Try(_body, _handlers, _orelse, _finalbody, _lineno, _col_offset)
+
+State.ast_type('Try', 'stmt', ['body', 'handlers', 'orelse', 'finalbody'])
class Assert(stmt):
@@ -3651,9 +3607,7 @@
return self.default_visitor(node)
def visit_Raise(self, node):
return self.default_visitor(node)
- def visit_TryExcept(self, node):
- return self.default_visitor(node)
- def visit_TryFinally(self, node):
+ def visit_Try(self, node):
return self.default_visitor(node)
def visit_Assert(self, node):
return self.default_visitor(node)
@@ -3818,13 +3772,10 @@
if node.cause:
node.cause.walkabout(self)
- def visit_TryExcept(self, node):
+ def visit_Try(self, node):
self.visit_sequence(node.body)
self.visit_sequence(node.handlers)
self.visit_sequence(node.orelse)
-
- def visit_TryFinally(self, node):
- self.visit_sequence(node.body)
self.visit_sequence(node.finalbody)
def visit_Assert(self, node):
diff --git a/pypy/interpreter/astcompiler/astbuilder.py
b/pypy/interpreter/astcompiler/astbuilder.py
--- a/pypy/interpreter/astcompiler/astbuilder.py
+++ b/pypy/interpreter/astcompiler/astbuilder.py
@@ -399,20 +399,15 @@
else:
otherwise = self.handle_suite(try_node.children[-1])
except_count -= 1
+ handlers = []
if except_count:
- handlers = []
for i in range(except_count):
base_offset = i * 3
exc = try_node.children[3 + base_offset]
except_body = try_node.children[5 + base_offset]
handlers.append(self.handle_except_clause(exc, except_body))
- except_ast = ast.TryExcept(body, handlers, otherwise,
- try_node.lineno, try_node.column)
- if finally_suite is None:
- return except_ast
- body = [except_ast]
- return ast.TryFinally(body, finally_suite, try_node.lineno,
- try_node.column)
+ return ast.Try(body, handlers, otherwise, finally_suite,
+ try_node.lineno, try_node.column)
def handle_with_stmt(self, with_node):
body = self.handle_suite(with_node.children[-1])
diff --git a/pypy/interpreter/astcompiler/codegen.py
b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -599,20 +599,20 @@
self.visit_sequence(wh.orelse)
self.use_next_block(end)
- def visit_TryExcept(self, te):
- self.update_position(te.lineno, True)
+ def _visit_try_except(self, tr):
+ self.update_position(tr.lineno, True)
exc = self.new_block()
otherwise = self.new_block()
end = self.new_block()
self.emit_jump(ops.SETUP_EXCEPT, exc)
body = self.use_next_block()
self.push_frame_block(F_BLOCK_EXCEPT, body)
- self.visit_sequence(te.body)
+ self.visit_sequence(tr.body)
self.emit_op(ops.POP_BLOCK)
self.pop_frame_block(F_BLOCK_EXCEPT, body)
self.emit_jump(ops.JUMP_FORWARD, otherwise)
self.use_next_block(exc)
- for handler in te.handlers:
+ for handler in tr.handlers:
assert isinstance(handler, ast.ExceptHandler)
self.update_position(handler.lineno, True)
next_except = self.new_block()
@@ -672,26 +672,35 @@
self.emit_op(ops.END_FINALLY) # this END_FINALLY will always re-raise
self.is_dead_code()
self.use_next_block(otherwise)
- self.visit_sequence(te.orelse)
+ self.visit_sequence(tr.orelse)
self.use_next_block(end)
- def visit_TryFinally(self, tf):
- self.update_position(tf.lineno, True)
+ def _visit_try_finally(self, tr):
+ self.update_position(tr.lineno, True)
end = self.new_block()
self.emit_jump(ops.SETUP_FINALLY, end)
body = self.use_next_block()
self.push_frame_block(F_BLOCK_FINALLY, body)
- self.visit_sequence(tf.body)
+ if tr.handlers:
+ self._visit_try_except(tr)
+ else:
+ self.visit_sequence(tr.body)
self.emit_op(ops.POP_BLOCK)
self.pop_frame_block(F_BLOCK_FINALLY, body)
# Indicates there was no exception.
self.load_const(self.space.w_None)
self.use_next_block(end)
self.push_frame_block(F_BLOCK_FINALLY_END, end)
- self.visit_sequence(tf.finalbody)
+ self.visit_sequence(tr.finalbody)
self.emit_op(ops.END_FINALLY)
self.pop_frame_block(F_BLOCK_FINALLY_END, end)
+ def visit_Try(self, tr):
+ if tr.finalbody:
+ return self._visit_try_finally(tr)
+ else:
+ return self._visit_try_except(tr)
+
def _import_as(self, alias):
source_name = alias.name
dot = source_name.find(".")
diff --git a/pypy/interpreter/astcompiler/symtable.py
b/pypy/interpreter/astcompiler/symtable.py
--- a/pypy/interpreter/astcompiler/symtable.py
+++ b/pypy/interpreter/astcompiler/symtable.py
@@ -557,15 +557,10 @@
role = SYM_ASSIGNED
self.note_symbol(name.id, role)
- def visit_TryExcept(self, node):
+ def visit_Try(self, node):
self.scope.note_try_start(node)
self.visit_sequence(node.body)
self.scope.note_try_end(node)
self.visit_sequence(node.handlers)
self.visit_sequence(node.orelse)
-
- def visit_TryFinally(self, node):
- self.scope.note_try_start(node)
- self.visit_sequence(node.body)
- self.scope.note_try_end(node)
self.visit_sequence(node.finalbody)
diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py
b/pypy/interpreter/astcompiler/test/test_astbuilder.py
--- a/pypy/interpreter/astcompiler/test/test_astbuilder.py
+++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py
@@ -306,14 +306,15 @@
def test_try(self):
tr = self.get_first_stmt("try: x" + "\n" +
"finally: pass")
- assert isinstance(tr, ast.TryFinally)
+ assert isinstance(tr, ast.Try)
assert len(tr.body) == 1
assert isinstance(tr.body[0].value, ast.Name)
assert len(tr.finalbody) == 1
assert isinstance(tr.finalbody[0], ast.Pass)
+ assert tr.orelse is None
tr = self.get_first_stmt("try: x" + "\n" +
"except: pass")
- assert isinstance(tr, ast.TryExcept)
+ assert isinstance(tr, ast.Try)
assert len(tr.body) == 1
assert isinstance(tr.body[0].value, ast.Name)
assert len(tr.handlers) == 1
@@ -324,6 +325,7 @@
assert len(handler.body) == 1
assert isinstance(handler.body[0], ast.Pass)
assert tr.orelse is None
+ assert tr.finalbody is None
tr = self.get_first_stmt("try: x" + "\n" +
"except Exception: pass")
assert len(tr.handlers) == 1
@@ -375,32 +377,27 @@
tr = self.get_first_stmt("try: x" + "\n" +
"except: 4" + "\n" +
"finally: pass")
- assert isinstance(tr, ast.TryFinally)
+ assert isinstance(tr, ast.Try)
assert len(tr.finalbody) == 1
assert isinstance(tr.finalbody[0], ast.Pass)
+ assert len(tr.handlers) == 1
+ assert len(tr.handlers[0].body) == 1
+ assert isinstance(tr.handlers[0].body[0].value, ast.Num)
assert len(tr.body) == 1
- exc = tr.body[0]
- assert isinstance(exc, ast.TryExcept)
- assert len(exc.handlers) == 1
- assert len(exc.handlers[0].body) == 1
- assert isinstance(exc.handlers[0].body[0].value, ast.Num)
- assert len(exc.body) == 1
- assert isinstance(exc.body[0].value, ast.Name)
+ assert isinstance(tr.body[0].value, ast.Name)
tr = self.get_first_stmt("try: x" + "\n" +
"except: 4" + "\n" +
"else: 'hi'" + "\n" +
"finally: pass")
- assert isinstance(tr, ast.TryFinally)
+ assert isinstance(tr, ast.Try)
assert len(tr.finalbody) == 1
assert isinstance(tr.finalbody[0], ast.Pass)
assert len(tr.body) == 1
- exc = tr.body[0]
- assert isinstance(exc, ast.TryExcept)
- assert len(exc.orelse) == 1
- assert isinstance(exc.orelse[0].value, ast.Str)
- assert len(exc.body) == 1
- assert isinstance(exc.body[0].value, ast.Name)
- assert len(exc.handlers) == 1
+ assert len(tr.orelse) == 1
+ assert isinstance(tr.orelse[0].value, ast.Str)
+ assert len(tr.body) == 1
+ assert isinstance(tr.body[0].value, ast.Name)
+ assert len(tr.handlers) == 1
def test_with(self):
wi = self.get_first_stmt("with x: pass")
diff --git a/pypy/interpreter/astcompiler/tools/Python.asdl
b/pypy/interpreter/astcompiler/tools/Python.asdl
--- a/pypy/interpreter/astcompiler/tools/Python.asdl
+++ b/pypy/interpreter/astcompiler/tools/Python.asdl
@@ -31,8 +31,7 @@
| With(withitem* items, stmt* body)
| Raise(expr? exc, expr? cause)
- | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)
- | TryFinally(stmt* body, stmt* finalbody)
+ | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt*
finalbody)
| Assert(expr test, expr? msg)
| Import(alias* names)
diff --git a/pypy/interpreter/astcompiler/validate.py
b/pypy/interpreter/astcompiler/validate.py
--- a/pypy/interpreter/astcompiler/validate.py
+++ b/pypy/interpreter/astcompiler/validate.py
@@ -240,15 +240,12 @@
elif node.cause:
raise ValidationError("Raise with cause but no exception")
- def visit_TryExcept(self, node):
- self._validate_body(node.body, "TryExcept")
+ def visit_Try(self, node):
+ self._validate_body(node.body, "Try")
for handler in node.handlers:
handler.walkabout(self)
self._validate_stmts(node.orelse)
-
- def visit_TryFinally(self, node):
- self._validate_body(node.body, "TryFinally")
- self._validate_body(node.finalbody, "TryFinally")
+ self._validate_stmts(node.finalbody)
def visit_ExceptHandler(self, node):
if node.type:
diff --git a/pypy/module/_ast/test/test_ast.py
b/pypy/module/_ast/test/test_ast.py
--- a/pypy/module/_ast/test/test_ast.py
+++ b/pypy/module/_ast/test/test_ast.py
@@ -359,11 +359,12 @@
def test_issue793(self):
import _ast as ast
body = ast.Module([
- ast.TryExcept([ast.Pass(lineno=2, col_offset=4)],
+ ast.Try([ast.Pass(lineno=2, col_offset=4)],
[ast.ExceptHandler(ast.Name('Exception', ast.Load(),
lineno=3, col_offset=0),
- None, [], lineno=4, col_offset=0)],
- [], lineno=1, col_offset=0)
+ None, [ast.Pass(lineno=4, col_offset=0)],
+ lineno=4, col_offset=0)],
+ [], [], lineno=1, col_offset=0)
])
exec(compile(body, '<string>', 'exec'))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit