[Python-checkins] commit of r41740 - in python/trunk: Grammar/Grammar Lib/test/test_exception_variations.py Misc/ACKS Python/ast.c Python/graminit.c

neal.norwitz python-checkins at python.org
Sat Dec 17 22:33:48 CET 2005


Author: neal.norwitz
Date: Sat Dec 17 22:33:47 2005
New Revision: 41740

Added:
   python/trunk/Lib/test/test_exception_variations.py
Modified:
   python/trunk/Grammar/Grammar
   python/trunk/Misc/ACKS
   python/trunk/Python/ast.c
   python/trunk/Python/graminit.c
Log:
SF patch #1355913, PEP 341 - Unification of try/except and try/finally

Modified since ast-arenas was implemented.


Modified: python/trunk/Grammar/Grammar
==============================================================================
--- python/trunk/Grammar/Grammar	(original)
+++ python/trunk/Grammar/Grammar	Sat Dec 17 22:33:47 2005
@@ -67,8 +67,7 @@
 if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
 while_stmt: 'while' test ':' suite ['else' ':' suite]
 for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
-try_stmt: ('try' ':' suite (except_clause ':' suite)+ #diagram:break
-           ['else' ':' suite] | 'try' ':' suite 'finally' ':' suite)
+try_stmt: 'try' ':' suite ((except_clause ':' suite)+ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)
 # NB compile.c makes sure that the default except clause is last
 except_clause: 'except' [test [',' test]]
 suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT

Added: python/trunk/Lib/test/test_exception_variations.py
==============================================================================
--- (empty file)
+++ python/trunk/Lib/test/test_exception_variations.py	Sat Dec 17 22:33:47 2005
@@ -0,0 +1,180 @@
+
+from test.test_support import run_unittest
+import unittest
+
+class ExceptionTestCase(unittest.TestCase):
+    def test_try_except_else_finally(self):
+        hit_except = False
+        hit_else = False
+        hit_finally = False
+
+        try:
+            raise Exception, 'nyaa!'
+        except:
+            hit_except = True
+        else:
+            hit_else = True
+        finally:
+            hit_finally = True
+
+        self.assertTrue(hit_except)
+        self.assertTrue(hit_finally)
+        self.assertFalse(hit_else)
+
+    def test_try_except_else_finally_no_exception(self):
+        hit_except = False
+        hit_else = False
+        hit_finally = False
+
+        try:
+            pass
+        except:
+            hit_except = True
+        else:
+            hit_else = True
+        finally:
+            hit_finally = True
+
+        self.assertFalse(hit_except)
+        self.assertTrue(hit_finally)
+        self.assertTrue(hit_else)
+
+    def test_try_except_finally(self):
+        hit_except = False
+        hit_finally = False
+
+        try:
+            raise Exception, 'yarr!'
+        except:
+            hit_except = True
+        finally:
+            hit_finally = True
+            
+        self.assertTrue(hit_except)
+        self.assertTrue(hit_finally)
+
+    def test_try_except_finally_no_exception(self):
+        hit_except = False
+        hit_finally = False
+
+        try:
+            pass
+        except:
+            hit_except = True
+        finally:
+            hit_finally = True
+
+        self.assertFalse(hit_except)
+        self.assertTrue(hit_finally)
+        
+    def test_try_except(self):
+        hit_except = False
+
+        try:
+            raise Exception, 'ahoy!'
+        except:
+            hit_except = True
+
+        self.assertTrue(hit_except)
+
+    def test_try_except_no_exception(self):
+        hit_except = False
+
+        try:
+            pass
+        except:
+            hit_except = True
+
+        self.assertFalse(hit_except)
+
+    def test_try_except_else(self):
+        hit_except = False
+        hit_else = False
+
+        try:
+            raise Exception, 'foo!'
+        except:
+            hit_except = True
+        else:
+            hit_else = True
+
+        self.assertFalse(hit_else)
+        self.assertTrue(hit_except)
+
+    def test_try_except_else_no_exception(self):
+        hit_except = False
+        hit_else = False
+
+        try:
+            pass
+        except:
+            hit_except = True
+        else:
+            hit_else = True
+
+        self.assertFalse(hit_except)
+        self.assertTrue(hit_else)
+
+    def test_try_finally_no_exception(self):
+        hit_finally = False
+
+        try:
+            pass
+        finally:
+            hit_finally = True
+
+        self.assertTrue(hit_finally)
+
+    def test_nested(self):
+        hit_finally = False
+        hit_inner_except = False
+        hit_inner_finally = False
+
+        try:
+            try:
+                raise Exception, 'inner exception'
+            except:
+                hit_inner_except = True
+            finally:
+                hit_inner_finally = True
+        finally:
+            hit_finally = True
+            
+        self.assertTrue(hit_inner_except)
+        self.assertTrue(hit_inner_finally)
+        self.assertTrue(hit_finally)
+
+    def test_nested_else(self):
+        hit_else = False
+        hit_finally = False
+        hit_except = False
+        hit_inner_except = False
+        hit_inner_else = False
+
+        try:
+            try:
+                pass
+            except:
+                hit_inner_except = True
+            else:
+                hit_inner_else = True
+
+            raise Exception, 'outer exception'
+        except:
+            hit_except = True
+        else:
+            hit_else = True
+        finally:
+            hit_finally = True
+
+        self.assertFalse(hit_inner_except)
+        self.assertTrue(hit_inner_else)
+        self.assertFalse(hit_else)
+        self.assertTrue(hit_finally)
+        self.assertTrue(hit_except)
+
+def test_main():
+    run_unittest(ExceptionTestCase)
+
+if __name__ == '__main__':
+    test_main()

Modified: python/trunk/Misc/ACKS
==============================================================================
--- python/trunk/Misc/ACKS	(original)
+++ python/trunk/Misc/ACKS	Sat Dec 17 22:33:47 2005
@@ -357,6 +357,7 @@
 Christopher Lee
 Inyeol Lee
 John J. Lee
+Thomas Lee
 Luc Lefebvre
 Kip Lehman
 Joerg Lehmann

Modified: python/trunk/Python/ast.c
==============================================================================
--- python/trunk/Python/ast.c	(original)
+++ python/trunk/Python/ast.c	Sat Dec 17 22:33:47 2005
@@ -2597,66 +2597,78 @@
 static stmt_ty
 ast_for_try_stmt(struct compiling *c, const node *n)
 {
+    const int nch = NCH(n);
+    int n_except = (nch - 3)/3;
+    asdl_seq *body, *orelse = NULL, *finally = NULL;
+
     REQ(n, try_stmt);
 
-    if (TYPE(CHILD(n, 3)) == NAME) {/* must be 'finally' */
-	/* try_stmt: 'try' ':' suite 'finally' ':' suite) */
-        asdl_seq *s1, *s2;
-        s1 = ast_for_suite(c, CHILD(n, 2));
-        if (!s1)
-            return NULL;
-        s2 = ast_for_suite(c, CHILD(n, 5));
-        if (!s2) {
-            return NULL;
-	}
-            
-	return TryFinally(s1, s2, LINENO(n), c->c_arena);
-    }
-    else if (TYPE(CHILD(n, 3)) == except_clause) {
-	/* try_stmt: ('try' ':' suite (except_clause ':' suite)+
-           ['else' ':' suite]
-	*/
-        asdl_seq *suite_seq1, *suite_seq2;
-	asdl_seq *handlers;
-	int i, has_else = 0, n_except = NCH(n) - 3;
-	if (TYPE(CHILD(n, NCH(n) - 3)) == NAME) {
-	    has_else = 1;
-	    n_except -= 3;
-	}
-	n_except /= 3;
-	handlers = asdl_seq_new(n_except, c->c_arena);
-	if (!handlers)
-		return NULL;
-	for (i = 0; i < n_except; i++) {
-            excepthandler_ty e = ast_for_except_clause(c,
-                                                       CHILD(n, 3 + i * 3),
-                                                       CHILD(n, 5 + i * 3));
-            if (!e) {
+    body = ast_for_suite(c, CHILD(n, 2));
+    if (body == NULL)
+        return NULL;
+
+    if (TYPE(CHILD(n, nch - 3)) == NAME) {
+        if (strcmp(STR(CHILD(n, nch - 3)), "finally") == 0) {
+            if (nch >= 9 && TYPE(CHILD(n, nch - 6)) == NAME) {
+                /* we can assume it's an "else",
+                   because nch >= 9 for try-else-finally and
+                   it would otherwise have a type of except_clause */
+                orelse = ast_for_suite(c, CHILD(n, nch - 4));
+                if (orelse == NULL)
+                    return NULL;
+                n_except--;
+            }
+
+            finally = ast_for_suite(c, CHILD(n, nch - 1));
+            if (finally == NULL)
                 return NULL;
-	    }
-	    asdl_seq_SET(handlers, i, e);
+            n_except--;
         }
-
-        suite_seq1 = ast_for_suite(c, CHILD(n, 2));
-        if (!suite_seq1) {
-            return NULL;
-	}
-        if (has_else) {
-            suite_seq2 = ast_for_suite(c, CHILD(n, NCH(n) - 1));
-            if (!suite_seq2) {
+        else {
+            /* we can assume it's an "else",
+               otherwise it would have a type of except_clause */
+            orelse = ast_for_suite(c, CHILD(n, nch - 1));
+            if (orelse == NULL)
                 return NULL;
-	    }
+            n_except--;
         }
-        else
-            suite_seq2 = NULL;
-
-	return TryExcept(suite_seq1, handlers, suite_seq2, LINENO(n),
-                         c->c_arena);
     }
-    else {
+    else if (TYPE(CHILD(n, nch - 3)) != except_clause) {
         ast_error(n, "malformed 'try' statement");
         return NULL;
     }
+    
+    if (n_except > 0) {
+	int i;
+	stmt_ty except_st;
+        /* process except statements to create a try ... except */
+        asdl_seq *handlers = asdl_seq_new(n_except, c->c_arena);
+        if (handlers == NULL)
+            return NULL;
+
+        for (i = 0; i < n_except; i++) {
+            excepthandler_ty e = ast_for_except_clause(c, CHILD(n, 3 + i * 3),
+                                                       CHILD(n, 5 + i * 3));
+            if (!e)
+                return NULL;
+            asdl_seq_SET(handlers, i, e);
+        }
+
+	except_st = TryExcept(body, handlers, orelse, LINENO(n), c->c_arena);
+        if (!finally)
+	    return except_st;
+
+        /* if a 'finally' is present too, we nest the TryExcept within a
+           TryFinally to emulate try ... except ... finally */
+	body = asdl_seq_new(1, c->c_arena);
+	if (body == NULL)
+	    return NULL;
+	asdl_seq_SET(body, 0, except_st);
+    }
+
+    /* must be a try ... finally (except clauses are in body, if any exist) */
+    assert(finally != NULL);
+    return TryFinally(body, finally, LINENO(n), c->c_arena);
 }
 
 static stmt_ty

Modified: python/trunk/Python/graminit.c
==============================================================================
--- python/trunk/Python/graminit.c	(original)
+++ python/trunk/Python/graminit.c	Sat Dec 17 22:33:47 2005
@@ -841,15 +841,26 @@
 static arc arcs_39_7[1] = {
 	{22, 9},
 };
-static arc arcs_39_8[3] = {
+static arc arcs_39_8[4] = {
 	{95, 4},
-	{91, 5},
+	{91, 10},
+	{96, 5},
 	{0, 8},
 };
 static arc arcs_39_9[1] = {
 	{0, 9},
 };
-static state states_39[10] = {
+static arc arcs_39_10[1] = {
+	{21, 11},
+};
+static arc arcs_39_11[1] = {
+	{22, 12},
+};
+static arc arcs_39_12[2] = {
+	{96, 5},
+	{0, 12},
+};
+static state states_39[13] = {
 	{1, arcs_39_0},
 	{1, arcs_39_1},
 	{1, arcs_39_2},
@@ -858,8 +869,11 @@
 	{1, arcs_39_5},
 	{1, arcs_39_6},
 	{1, arcs_39_7},
-	{3, arcs_39_8},
+	{4, arcs_39_8},
 	{1, arcs_39_9},
+	{1, arcs_39_10},
+	{1, arcs_39_11},
+	{2, arcs_39_12},
 };
 static arc arcs_40_0[1] = {
 	{97, 1},
@@ -1754,7 +1768,7 @@
 	 "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"},
 	{294, "for_stmt", 0, 10, states_38,
 	 "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"},
-	{295, "try_stmt", 0, 10, states_39,
+	{295, "try_stmt", 0, 13, states_39,
 	 "\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"},
 	{296, "except_clause", 0, 5, states_40,
 	 "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000"},


More information about the Python-checkins mailing list