Index: Python/ceval.c =================================================================== --- Python/ceval.c (revision 42621) +++ Python/ceval.c (working copy) @@ -97,6 +97,7 @@ #define CALL_FLAG_KW 2 #ifdef LLTRACE +static int lltrace; static int prtrace(PyObject *, char *); #endif static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *, @@ -540,9 +541,6 @@ unsigned char *first_instr; PyObject *names; PyObject *consts; -#ifdef LLTRACE - int lltrace; -#endif #if defined(Py_DEBUG) || defined(LLTRACE) /* Make it easier to find out where we are with a debugger */ char *filename; @@ -661,10 +659,12 @@ #define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \ lltrace && prtrace(TOP(), "stackadj")); \ assert(STACK_LEVEL() <= f->f_stacksize); } +#define EXT_POP(STACK_POINTER) (lltrace && prtrace(*(STACK_POINTER), "ext_pop"), *--(STACK_POINTER)) #else #define PUSH(v) BASIC_PUSH(v) #define POP() BASIC_POP() #define STACKADJ(n) BASIC_STACKADJ(n) +#define EXT_POP(STACK_POINTER) (*--(STACK_POINTER)) #endif /* Local variable macros */ @@ -998,6 +998,21 @@ SET_SECOND(w); SET_THIRD(v); goto fast_next_opcode; + } else if (oparg == 4) { + x = TOP(); + Py_INCREF(x); + w = SECOND(); + Py_INCREF(w); + v = THIRD(); + Py_INCREF(v); + u = FOURTH(); + Py_INCREF(u); + STACKADJ(4); + SET_TOP(x); + SET_SECOND(w); + SET_THIRD(v); + SET_FOURTH(u); + goto fast_next_opcode; } Py_FatalError("invalid argument to DUP_TOPX" " (bytecode corruption?)"); @@ -2172,6 +2187,43 @@ STACK_LEVEL()); continue; + case WITH_CLEANUP: + { + /* TOP is the context.__exit__ bound method. + Below that are 1-3 values indicating how/why + we entered the finally clause: + - SECOND = None + - (SECOND, THIRD) = (WHY_RETURN or WHY_CONTINUE), retval + - SECOND = WHY_*; no retval below it + - (SECOND, THIRD, FOURTH) = exc_info() + In the last case, we must call + TOP(SECOND, THIRD, FOURTH) + otherwise we must call + TOP(None, None, None) + but we must preserve the stack entries below TOP. + The code here just sets the stack up for the call; + separate CALL_FUNCTION(3) and POP_TOP opcodes are + emitted by the compiler. + */ + + x = TOP(); + u = SECOND(); + if (PyInt_Check(u) || u == Py_None) { + u = v = w = Py_None; + } + else { + v = THIRD(); + w = FOURTH(); + } + Py_INCREF(u); + Py_INCREF(v); + Py_INCREF(w); + PUSH(u); + PUSH(v); + PUSH(w); + break; + } + case CALL_FUNCTION: { PyObject **sp; @@ -2511,9 +2563,9 @@ return retval; } -/* this is gonna seem *real weird*, but if you put some other code between +/* This is gonna seem *real weird*, but if you put some other code between PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust - the test in the if statement in Misc/gdbinit:pystack* */ + the test in the if statements in Misc/gdbinit (pystack and pystackv). */ PyObject * PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, @@ -3473,8 +3525,6 @@ } } -#define EXT_POP(STACK_POINTER) (*--(STACK_POINTER)) - static void err_args(PyObject *func, int flags, int nargs) { @@ -4359,3 +4409,4 @@ } #endif + Index: Python/graminit.c =================================================================== --- Python/graminit.c (revision 42621) +++ Python/graminit.c (working copy) @@ -688,23 +688,24 @@ {1, arcs_34_3}, {1, arcs_34_4}, }; -static arc arcs_35_0[6] = { +static arc arcs_35_0[7] = { {84, 1}, {85, 1}, {86, 1}, {87, 1}, + {88, 1}, {17, 1}, - {88, 1}, + {89, 1}, }; static arc arcs_35_1[1] = { {0, 1}, }; static state states_35[2] = { - {6, arcs_35_0}, + {7, arcs_35_0}, {1, arcs_35_1}, }; static arc arcs_36_0[1] = { - {89, 1}, + {90, 1}, }; static arc arcs_36_1[1] = { {26, 2}, @@ -716,8 +717,8 @@ {22, 4}, }; static arc arcs_36_4[3] = { - {90, 1}, - {91, 5}, + {91, 1}, + {92, 5}, {0, 4}, }; static arc arcs_36_5[1] = { @@ -740,7 +741,7 @@ {1, arcs_36_7}, }; static arc arcs_37_0[1] = { - {92, 1}, + {93, 1}, }; static arc arcs_37_1[1] = { {26, 2}, @@ -752,7 +753,7 @@ {22, 4}, }; static arc arcs_37_4[2] = { - {91, 5}, + {92, 5}, {0, 4}, }; static arc arcs_37_5[1] = { @@ -775,7 +776,7 @@ {1, arcs_37_7}, }; static arc arcs_38_0[1] = { - {93, 1}, + {94, 1}, }; static arc arcs_38_1[1] = { {59, 2}, @@ -793,7 +794,7 @@ {22, 6}, }; static arc arcs_38_6[2] = { - {91, 7}, + {92, 7}, {0, 6}, }; static arc arcs_38_7[1] = { @@ -818,7 +819,7 @@ {1, arcs_38_9}, }; static arc arcs_39_0[1] = { - {94, 1}, + {95, 1}, }; static arc arcs_39_1[1] = { {21, 2}, @@ -827,8 +828,8 @@ {22, 3}, }; static arc arcs_39_3[2] = { - {95, 4}, - {96, 5}, + {96, 4}, + {97, 5}, }; static arc arcs_39_4[1] = { {21, 6}, @@ -843,9 +844,9 @@ {22, 9}, }; static arc arcs_39_8[4] = { - {95, 4}, - {91, 10}, - {96, 5}, + {96, 4}, + {92, 10}, + {97, 5}, {0, 8}, }; static arc arcs_39_9[1] = { @@ -858,7 +859,7 @@ {22, 12}, }; static arc arcs_39_12[2] = { - {96, 5}, + {97, 5}, {0, 12}, }; static state states_39[13] = { @@ -877,179 +878,204 @@ {2, arcs_39_12}, }; static arc arcs_40_0[1] = { - {97, 1}, + {98, 1}, }; -static arc arcs_40_1[2] = { +static arc arcs_40_1[1] = { {26, 2}, - {0, 1}, }; static arc arcs_40_2[2] = { - {27, 3}, - {0, 2}, + {99, 3}, + {21, 4}, }; static arc arcs_40_3[1] = { - {26, 4}, + {21, 4}, }; static arc arcs_40_4[1] = { - {0, 4}, + {22, 5}, }; -static state states_40[5] = { +static arc arcs_40_5[1] = { + {0, 5}, +}; +static state states_40[6] = { {1, arcs_40_0}, - {2, arcs_40_1}, + {1, arcs_40_1}, {2, arcs_40_2}, {1, arcs_40_3}, {1, arcs_40_4}, + {1, arcs_40_5}, }; -static arc arcs_41_0[2] = { - {3, 1}, - {2, 2}, +static arc arcs_41_0[1] = { + {19, 1}, }; -static arc arcs_41_1[1] = { - {0, 1}, +static arc arcs_41_1[2] = { + {12, 2}, + {13, 3}, }; static arc arcs_41_2[1] = { - {98, 3}, + {0, 2}, }; static arc arcs_41_3[1] = { - {6, 4}, + {12, 4}, }; static arc arcs_41_4[2] = { - {6, 4}, - {99, 1}, + {27, 3}, + {15, 2}, }; static state states_41[5] = { - {2, arcs_41_0}, - {1, arcs_41_1}, + {1, arcs_41_0}, + {2, arcs_41_1}, {1, arcs_41_2}, {1, arcs_41_3}, {2, arcs_41_4}, }; static arc arcs_42_0[1] = { - {101, 1}, + {100, 1}, }; static arc arcs_42_1[2] = { - {27, 2}, + {26, 2}, {0, 1}, }; -static arc arcs_42_2[1] = { - {101, 3}, +static arc arcs_42_2[2] = { + {27, 3}, + {0, 2}, }; -static arc arcs_42_3[2] = { - {27, 4}, - {0, 3}, +static arc arcs_42_3[1] = { + {26, 4}, }; -static arc arcs_42_4[2] = { - {101, 3}, +static arc arcs_42_4[1] = { {0, 4}, }; static state states_42[5] = { {1, arcs_42_0}, {2, arcs_42_1}, - {1, arcs_42_2}, - {2, arcs_42_3}, - {2, arcs_42_4}, + {2, arcs_42_2}, + {1, arcs_42_3}, + {1, arcs_42_4}, }; static arc arcs_43_0[2] = { - {102, 1}, - {103, 1}, + {3, 1}, + {2, 2}, }; static arc arcs_43_1[1] = { {0, 1}, }; -static state states_43[2] = { +static arc arcs_43_2[1] = { + {101, 3}, +}; +static arc arcs_43_3[1] = { + {6, 4}, +}; +static arc arcs_43_4[2] = { + {6, 4}, + {102, 1}, +}; +static state states_43[5] = { {2, arcs_43_0}, {1, arcs_43_1}, + {1, arcs_43_2}, + {1, arcs_43_3}, + {2, arcs_43_4}, }; static arc arcs_44_0[1] = { {104, 1}, }; static arc arcs_44_1[2] = { - {23, 2}, - {21, 3}, + {27, 2}, + {0, 1}, }; static arc arcs_44_2[1] = { - {21, 3}, + {104, 3}, }; -static arc arcs_44_3[1] = { - {101, 4}, +static arc arcs_44_3[2] = { + {27, 4}, + {0, 3}, }; -static arc arcs_44_4[1] = { +static arc arcs_44_4[2] = { + {104, 3}, {0, 4}, }; static state states_44[5] = { {1, arcs_44_0}, {2, arcs_44_1}, {1, arcs_44_2}, - {1, arcs_44_3}, - {1, arcs_44_4}, + {2, arcs_44_3}, + {2, arcs_44_4}, }; static arc arcs_45_0[2] = { - {102, 1}, - {105, 2}, + {105, 1}, + {106, 1}, }; -static arc arcs_45_1[2] = { - {89, 3}, +static arc arcs_45_1[1] = { {0, 1}, }; -static arc arcs_45_2[1] = { - {0, 2}, +static state states_45[2] = { + {2, arcs_45_0}, + {1, arcs_45_1}, }; -static arc arcs_45_3[1] = { - {102, 4}, +static arc arcs_46_0[1] = { + {107, 1}, }; -static arc arcs_45_4[1] = { - {91, 5}, +static arc arcs_46_1[2] = { + {23, 2}, + {21, 3}, }; -static arc arcs_45_5[1] = { - {26, 2}, +static arc arcs_46_2[1] = { + {21, 3}, }; -static state states_45[6] = { - {2, arcs_45_0}, - {2, arcs_45_1}, - {1, arcs_45_2}, - {1, arcs_45_3}, - {1, arcs_45_4}, - {1, arcs_45_5}, +static arc arcs_46_3[1] = { + {104, 4}, }; -static arc arcs_46_0[1] = { - {106, 1}, +static arc arcs_46_4[1] = { + {0, 4}, }; -static arc arcs_46_1[2] = { - {107, 0}, - {0, 1}, -}; -static state states_46[2] = { +static state states_46[5] = { {1, arcs_46_0}, {2, arcs_46_1}, + {1, arcs_46_2}, + {1, arcs_46_3}, + {1, arcs_46_4}, }; -static arc arcs_47_0[1] = { - {108, 1}, +static arc arcs_47_0[2] = { + {105, 1}, + {108, 2}, }; static arc arcs_47_1[2] = { - {109, 0}, + {90, 3}, {0, 1}, }; -static state states_47[2] = { - {1, arcs_47_0}, +static arc arcs_47_2[1] = { + {0, 2}, +}; +static arc arcs_47_3[1] = { + {105, 4}, +}; +static arc arcs_47_4[1] = { + {92, 5}, +}; +static arc arcs_47_5[1] = { + {26, 2}, +}; +static state states_47[6] = { + {2, arcs_47_0}, {2, arcs_47_1}, + {1, arcs_47_2}, + {1, arcs_47_3}, + {1, arcs_47_4}, + {1, arcs_47_5}, }; -static arc arcs_48_0[2] = { - {110, 1}, - {111, 2}, +static arc arcs_48_0[1] = { + {109, 1}, }; -static arc arcs_48_1[1] = { - {108, 2}, +static arc arcs_48_1[2] = { + {110, 0}, + {0, 1}, }; -static arc arcs_48_2[1] = { - {0, 2}, +static state states_48[2] = { + {1, arcs_48_0}, + {2, arcs_48_1}, }; -static state states_48[3] = { - {2, arcs_48_0}, - {1, arcs_48_1}, - {1, arcs_48_2}, -}; static arc arcs_49_0[1] = { - {81, 1}, + {111, 1}, }; static arc arcs_49_1[2] = { {112, 0}, @@ -1059,61 +1085,65 @@ {1, arcs_49_0}, {2, arcs_49_1}, }; -static arc arcs_50_0[10] = { +static arc arcs_50_0[2] = { {113, 1}, - {114, 1}, - {115, 1}, - {116, 1}, - {117, 1}, - {118, 1}, - {119, 1}, - {82, 1}, - {110, 2}, - {120, 3}, + {114, 2}, }; static arc arcs_50_1[1] = { - {0, 1}, + {111, 2}, }; static arc arcs_50_2[1] = { - {82, 1}, + {0, 2}, }; -static arc arcs_50_3[2] = { - {110, 1}, - {0, 3}, -}; -static state states_50[4] = { - {10, arcs_50_0}, +static state states_50[3] = { + {2, arcs_50_0}, {1, arcs_50_1}, {1, arcs_50_2}, - {2, arcs_50_3}, }; static arc arcs_51_0[1] = { - {121, 1}, + {81, 1}, }; static arc arcs_51_1[2] = { - {122, 0}, + {115, 0}, {0, 1}, }; static state states_51[2] = { {1, arcs_51_0}, {2, arcs_51_1}, }; -static arc arcs_52_0[1] = { - {123, 1}, +static arc arcs_52_0[10] = { + {116, 1}, + {117, 1}, + {118, 1}, + {119, 1}, + {120, 1}, + {121, 1}, + {122, 1}, + {82, 1}, + {113, 2}, + {123, 3}, }; -static arc arcs_52_1[2] = { - {124, 0}, +static arc arcs_52_1[1] = { {0, 1}, }; -static state states_52[2] = { - {1, arcs_52_0}, - {2, arcs_52_1}, +static arc arcs_52_2[1] = { + {82, 1}, }; +static arc arcs_52_3[2] = { + {113, 1}, + {0, 3}, +}; +static state states_52[4] = { + {10, arcs_52_0}, + {1, arcs_52_1}, + {1, arcs_52_2}, + {2, arcs_52_3}, +}; static arc arcs_53_0[1] = { - {125, 1}, + {124, 1}, }; static arc arcs_53_1[2] = { - {126, 0}, + {125, 0}, {0, 1}, }; static state states_53[2] = { @@ -1121,622 +1151,644 @@ {2, arcs_53_1}, }; static arc arcs_54_0[1] = { - {127, 1}, + {126, 1}, }; -static arc arcs_54_1[3] = { - {128, 0}, - {57, 0}, +static arc arcs_54_1[2] = { + {127, 0}, {0, 1}, }; static state states_54[2] = { {1, arcs_54_0}, - {3, arcs_54_1}, + {2, arcs_54_1}, }; static arc arcs_55_0[1] = { - {129, 1}, + {128, 1}, }; -static arc arcs_55_1[3] = { - {130, 0}, - {131, 0}, +static arc arcs_55_1[2] = { + {129, 0}, {0, 1}, }; static state states_55[2] = { {1, arcs_55_0}, - {3, arcs_55_1}, + {2, arcs_55_1}, }; static arc arcs_56_0[1] = { + {130, 1}, +}; +static arc arcs_56_1[3] = { + {131, 0}, + {57, 0}, + {0, 1}, +}; +static state states_56[2] = { + {1, arcs_56_0}, + {3, arcs_56_1}, +}; +static arc arcs_57_0[1] = { {132, 1}, }; -static arc arcs_56_1[5] = { - {28, 0}, +static arc arcs_57_1[3] = { {133, 0}, {134, 0}, - {135, 0}, {0, 1}, }; -static state states_56[2] = { - {1, arcs_56_0}, - {5, arcs_56_1}, +static state states_57[2] = { + {1, arcs_57_0}, + {3, arcs_57_1}, }; -static arc arcs_57_0[4] = { - {130, 1}, - {131, 1}, - {136, 1}, - {137, 2}, +static arc arcs_58_0[1] = { + {135, 1}, }; -static arc arcs_57_1[1] = { - {132, 2}, +static arc arcs_58_1[5] = { + {28, 0}, + {136, 0}, + {137, 0}, + {138, 0}, + {0, 1}, }; -static arc arcs_57_2[1] = { +static state states_58[2] = { + {1, arcs_58_0}, + {5, arcs_58_1}, +}; +static arc arcs_59_0[4] = { + {133, 1}, + {134, 1}, + {139, 1}, + {140, 2}, +}; +static arc arcs_59_1[1] = { + {135, 2}, +}; +static arc arcs_59_2[1] = { {0, 2}, }; -static state states_57[3] = { - {4, arcs_57_0}, - {1, arcs_57_1}, - {1, arcs_57_2}, +static state states_59[3] = { + {4, arcs_59_0}, + {1, arcs_59_1}, + {1, arcs_59_2}, }; -static arc arcs_58_0[1] = { - {138, 1}, +static arc arcs_60_0[1] = { + {141, 1}, }; -static arc arcs_58_1[3] = { - {139, 1}, +static arc arcs_60_1[3] = { + {142, 1}, {29, 2}, {0, 1}, }; -static arc arcs_58_2[1] = { - {132, 3}, +static arc arcs_60_2[1] = { + {135, 3}, }; -static arc arcs_58_3[1] = { +static arc arcs_60_3[1] = { {0, 3}, }; -static state states_58[4] = { - {1, arcs_58_0}, - {3, arcs_58_1}, - {1, arcs_58_2}, - {1, arcs_58_3}, +static state states_60[4] = { + {1, arcs_60_0}, + {3, arcs_60_1}, + {1, arcs_60_2}, + {1, arcs_60_3}, }; -static arc arcs_59_0[7] = { +static arc arcs_61_0[7] = { {13, 1}, - {141, 2}, - {144, 3}, - {147, 4}, + {144, 2}, + {147, 3}, + {150, 4}, {19, 5}, - {149, 5}, - {150, 6}, + {152, 5}, + {153, 6}, }; -static arc arcs_59_1[3] = { +static arc arcs_61_1[3] = { {43, 7}, - {140, 7}, + {143, 7}, {15, 5}, }; -static arc arcs_59_2[2] = { - {142, 8}, - {143, 5}, -}; -static arc arcs_59_3[2] = { - {145, 9}, +static arc arcs_61_2[2] = { + {145, 8}, {146, 5}, }; -static arc arcs_59_4[1] = { - {148, 10}, +static arc arcs_61_3[2] = { + {148, 9}, + {149, 5}, }; -static arc arcs_59_5[1] = { +static arc arcs_61_4[1] = { + {151, 10}, +}; +static arc arcs_61_5[1] = { {0, 5}, }; -static arc arcs_59_6[2] = { - {150, 6}, +static arc arcs_61_6[2] = { + {153, 6}, {0, 6}, }; -static arc arcs_59_7[1] = { +static arc arcs_61_7[1] = { {15, 5}, }; -static arc arcs_59_8[1] = { - {143, 5}, -}; -static arc arcs_59_9[1] = { +static arc arcs_61_8[1] = { {146, 5}, }; -static arc arcs_59_10[1] = { - {147, 5}, +static arc arcs_61_9[1] = { + {149, 5}, }; -static state states_59[11] = { - {7, arcs_59_0}, - {3, arcs_59_1}, - {2, arcs_59_2}, - {2, arcs_59_3}, - {1, arcs_59_4}, - {1, arcs_59_5}, - {2, arcs_59_6}, - {1, arcs_59_7}, - {1, arcs_59_8}, - {1, arcs_59_9}, - {1, arcs_59_10}, +static arc arcs_61_10[1] = { + {150, 5}, }; -static arc arcs_60_0[1] = { +static state states_61[11] = { + {7, arcs_61_0}, + {3, arcs_61_1}, + {2, arcs_61_2}, + {2, arcs_61_3}, + {1, arcs_61_4}, + {1, arcs_61_5}, + {2, arcs_61_6}, + {1, arcs_61_7}, + {1, arcs_61_8}, + {1, arcs_61_9}, + {1, arcs_61_10}, +}; +static arc arcs_62_0[1] = { {26, 1}, }; -static arc arcs_60_1[3] = { - {151, 2}, +static arc arcs_62_1[3] = { + {154, 2}, {27, 3}, {0, 1}, }; -static arc arcs_60_2[1] = { +static arc arcs_62_2[1] = { {0, 2}, }; -static arc arcs_60_3[2] = { +static arc arcs_62_3[2] = { {26, 4}, {0, 3}, }; -static arc arcs_60_4[2] = { +static arc arcs_62_4[2] = { {27, 3}, {0, 4}, }; -static state states_60[5] = { - {1, arcs_60_0}, - {3, arcs_60_1}, - {1, arcs_60_2}, - {2, arcs_60_3}, - {2, arcs_60_4}, +static state states_62[5] = { + {1, arcs_62_0}, + {3, arcs_62_1}, + {1, arcs_62_2}, + {2, arcs_62_3}, + {2, arcs_62_4}, }; -static arc arcs_61_0[1] = { +static arc arcs_63_0[1] = { {26, 1}, }; -static arc arcs_61_1[3] = { - {152, 2}, +static arc arcs_63_1[3] = { + {155, 2}, {27, 3}, {0, 1}, }; -static arc arcs_61_2[1] = { +static arc arcs_63_2[1] = { {0, 2}, }; -static arc arcs_61_3[2] = { +static arc arcs_63_3[2] = { {26, 4}, {0, 3}, }; -static arc arcs_61_4[2] = { +static arc arcs_63_4[2] = { {27, 3}, {0, 4}, }; -static state states_61[5] = { - {1, arcs_61_0}, - {3, arcs_61_1}, - {1, arcs_61_2}, - {2, arcs_61_3}, - {2, arcs_61_4}, +static state states_63[5] = { + {1, arcs_63_0}, + {3, arcs_63_1}, + {1, arcs_63_2}, + {2, arcs_63_3}, + {2, arcs_63_4}, }; -static arc arcs_62_0[1] = { - {104, 1}, +static arc arcs_64_0[1] = { + {107, 1}, }; -static arc arcs_62_1[2] = { +static arc arcs_64_1[2] = { {23, 2}, {21, 3}, }; -static arc arcs_62_2[1] = { +static arc arcs_64_2[1] = { {21, 3}, }; -static arc arcs_62_3[1] = { +static arc arcs_64_3[1] = { {26, 4}, }; -static arc arcs_62_4[1] = { +static arc arcs_64_4[1] = { {0, 4}, }; -static state states_62[5] = { - {1, arcs_62_0}, - {2, arcs_62_1}, - {1, arcs_62_2}, - {1, arcs_62_3}, - {1, arcs_62_4}, +static state states_64[5] = { + {1, arcs_64_0}, + {2, arcs_64_1}, + {1, arcs_64_2}, + {1, arcs_64_3}, + {1, arcs_64_4}, }; -static arc arcs_63_0[3] = { +static arc arcs_65_0[3] = { {13, 1}, - {141, 2}, + {144, 2}, {75, 3}, }; -static arc arcs_63_1[2] = { +static arc arcs_65_1[2] = { {14, 4}, {15, 5}, }; -static arc arcs_63_2[1] = { - {153, 6}, +static arc arcs_65_2[1] = { + {156, 6}, }; -static arc arcs_63_3[1] = { +static arc arcs_65_3[1] = { {19, 5}, }; -static arc arcs_63_4[1] = { +static arc arcs_65_4[1] = { {15, 5}, }; -static arc arcs_63_5[1] = { +static arc arcs_65_5[1] = { {0, 5}, }; -static arc arcs_63_6[1] = { - {143, 5}, +static arc arcs_65_6[1] = { + {146, 5}, }; -static state states_63[7] = { - {3, arcs_63_0}, - {2, arcs_63_1}, - {1, arcs_63_2}, - {1, arcs_63_3}, - {1, arcs_63_4}, - {1, arcs_63_5}, - {1, arcs_63_6}, +static state states_65[7] = { + {3, arcs_65_0}, + {2, arcs_65_1}, + {1, arcs_65_2}, + {1, arcs_65_3}, + {1, arcs_65_4}, + {1, arcs_65_5}, + {1, arcs_65_6}, }; -static arc arcs_64_0[1] = { - {154, 1}, +static arc arcs_66_0[1] = { + {157, 1}, }; -static arc arcs_64_1[2] = { +static arc arcs_66_1[2] = { {27, 2}, {0, 1}, }; -static arc arcs_64_2[2] = { - {154, 1}, +static arc arcs_66_2[2] = { + {157, 1}, {0, 2}, }; -static state states_64[3] = { - {1, arcs_64_0}, - {2, arcs_64_1}, - {2, arcs_64_2}, +static state states_66[3] = { + {1, arcs_66_0}, + {2, arcs_66_1}, + {2, arcs_66_2}, }; -static arc arcs_65_0[3] = { +static arc arcs_67_0[3] = { {75, 1}, {26, 2}, {21, 3}, }; -static arc arcs_65_1[1] = { +static arc arcs_67_1[1] = { {75, 4}, }; -static arc arcs_65_2[2] = { +static arc arcs_67_2[2] = { {21, 3}, {0, 2}, }; -static arc arcs_65_3[3] = { +static arc arcs_67_3[3] = { {26, 5}, - {155, 6}, + {158, 6}, {0, 3}, }; -static arc arcs_65_4[1] = { +static arc arcs_67_4[1] = { {75, 6}, }; -static arc arcs_65_5[2] = { - {155, 6}, +static arc arcs_67_5[2] = { + {158, 6}, {0, 5}, }; -static arc arcs_65_6[1] = { +static arc arcs_67_6[1] = { {0, 6}, }; -static state states_65[7] = { - {3, arcs_65_0}, - {1, arcs_65_1}, - {2, arcs_65_2}, - {3, arcs_65_3}, - {1, arcs_65_4}, - {2, arcs_65_5}, - {1, arcs_65_6}, +static state states_67[7] = { + {3, arcs_67_0}, + {1, arcs_67_1}, + {2, arcs_67_2}, + {3, arcs_67_3}, + {1, arcs_67_4}, + {2, arcs_67_5}, + {1, arcs_67_6}, }; -static arc arcs_66_0[1] = { +static arc arcs_68_0[1] = { {21, 1}, }; -static arc arcs_66_1[2] = { +static arc arcs_68_1[2] = { {26, 2}, {0, 1}, }; -static arc arcs_66_2[1] = { +static arc arcs_68_2[1] = { {0, 2}, }; -static state states_66[3] = { - {1, arcs_66_0}, - {2, arcs_66_1}, - {1, arcs_66_2}, +static state states_68[3] = { + {1, arcs_68_0}, + {2, arcs_68_1}, + {1, arcs_68_2}, }; -static arc arcs_67_0[1] = { +static arc arcs_69_0[1] = { {81, 1}, }; -static arc arcs_67_1[2] = { +static arc arcs_69_1[2] = { {27, 2}, {0, 1}, }; -static arc arcs_67_2[2] = { +static arc arcs_69_2[2] = { {81, 1}, {0, 2}, }; -static state states_67[3] = { - {1, arcs_67_0}, - {2, arcs_67_1}, - {2, arcs_67_2}, +static state states_69[3] = { + {1, arcs_69_0}, + {2, arcs_69_1}, + {2, arcs_69_2}, }; -static arc arcs_68_0[1] = { +static arc arcs_70_0[1] = { {26, 1}, }; -static arc arcs_68_1[2] = { +static arc arcs_70_1[2] = { {27, 2}, {0, 1}, }; -static arc arcs_68_2[2] = { +static arc arcs_70_2[2] = { {26, 1}, {0, 2}, }; -static state states_68[3] = { - {1, arcs_68_0}, - {2, arcs_68_1}, - {2, arcs_68_2}, +static state states_70[3] = { + {1, arcs_70_0}, + {2, arcs_70_1}, + {2, arcs_70_2}, }; -static arc arcs_69_0[1] = { +static arc arcs_71_0[1] = { {26, 1}, }; -static arc arcs_69_1[1] = { +static arc arcs_71_1[1] = { {21, 2}, }; -static arc arcs_69_2[1] = { +static arc arcs_71_2[1] = { {26, 3}, }; -static arc arcs_69_3[2] = { +static arc arcs_71_3[2] = { {27, 4}, {0, 3}, }; -static arc arcs_69_4[2] = { +static arc arcs_71_4[2] = { {26, 1}, {0, 4}, }; -static state states_69[5] = { - {1, arcs_69_0}, - {1, arcs_69_1}, - {1, arcs_69_2}, - {2, arcs_69_3}, - {2, arcs_69_4}, +static state states_71[5] = { + {1, arcs_71_0}, + {1, arcs_71_1}, + {1, arcs_71_2}, + {2, arcs_71_3}, + {2, arcs_71_4}, }; -static arc arcs_70_0[1] = { - {156, 1}, +static arc arcs_72_0[1] = { + {159, 1}, }; -static arc arcs_70_1[1] = { +static arc arcs_72_1[1] = { {19, 2}, }; -static arc arcs_70_2[2] = { +static arc arcs_72_2[2] = { {13, 3}, {21, 4}, }; -static arc arcs_70_3[2] = { +static arc arcs_72_3[2] = { {9, 5}, {15, 6}, }; -static arc arcs_70_4[1] = { +static arc arcs_72_4[1] = { {22, 7}, }; -static arc arcs_70_5[1] = { +static arc arcs_72_5[1] = { {15, 6}, }; -static arc arcs_70_6[1] = { +static arc arcs_72_6[1] = { {21, 4}, }; -static arc arcs_70_7[1] = { +static arc arcs_72_7[1] = { {0, 7}, }; -static state states_70[8] = { - {1, arcs_70_0}, - {1, arcs_70_1}, - {2, arcs_70_2}, - {2, arcs_70_3}, - {1, arcs_70_4}, - {1, arcs_70_5}, - {1, arcs_70_6}, - {1, arcs_70_7}, +static state states_72[8] = { + {1, arcs_72_0}, + {1, arcs_72_1}, + {2, arcs_72_2}, + {2, arcs_72_3}, + {1, arcs_72_4}, + {1, arcs_72_5}, + {1, arcs_72_6}, + {1, arcs_72_7}, }; -static arc arcs_71_0[3] = { - {157, 1}, +static arc arcs_73_0[3] = { + {160, 1}, {28, 2}, {29, 3}, }; -static arc arcs_71_1[2] = { +static arc arcs_73_1[2] = { {27, 4}, {0, 1}, }; -static arc arcs_71_2[1] = { +static arc arcs_73_2[1] = { {26, 5}, }; -static arc arcs_71_3[1] = { +static arc arcs_73_3[1] = { {26, 6}, }; -static arc arcs_71_4[4] = { - {157, 1}, +static arc arcs_73_4[4] = { + {160, 1}, {28, 2}, {29, 3}, {0, 4}, }; -static arc arcs_71_5[2] = { +static arc arcs_73_5[2] = { {27, 7}, {0, 5}, }; -static arc arcs_71_6[1] = { +static arc arcs_73_6[1] = { {0, 6}, }; -static arc arcs_71_7[1] = { +static arc arcs_73_7[1] = { {29, 3}, }; -static state states_71[8] = { - {3, arcs_71_0}, - {2, arcs_71_1}, - {1, arcs_71_2}, - {1, arcs_71_3}, - {4, arcs_71_4}, - {2, arcs_71_5}, - {1, arcs_71_6}, - {1, arcs_71_7}, +static state states_73[8] = { + {3, arcs_73_0}, + {2, arcs_73_1}, + {1, arcs_73_2}, + {1, arcs_73_3}, + {4, arcs_73_4}, + {2, arcs_73_5}, + {1, arcs_73_6}, + {1, arcs_73_7}, }; -static arc arcs_72_0[1] = { +static arc arcs_74_0[1] = { {26, 1}, }; -static arc arcs_72_1[3] = { - {152, 2}, +static arc arcs_74_1[3] = { + {155, 2}, {25, 3}, {0, 1}, }; -static arc arcs_72_2[1] = { +static arc arcs_74_2[1] = { {0, 2}, }; -static arc arcs_72_3[1] = { +static arc arcs_74_3[1] = { {26, 2}, }; -static state states_72[4] = { - {1, arcs_72_0}, - {3, arcs_72_1}, - {1, arcs_72_2}, - {1, arcs_72_3}, +static state states_74[4] = { + {1, arcs_74_0}, + {3, arcs_74_1}, + {1, arcs_74_2}, + {1, arcs_74_3}, }; -static arc arcs_73_0[2] = { - {151, 1}, - {159, 1}, +static arc arcs_75_0[2] = { + {154, 1}, + {162, 1}, }; -static arc arcs_73_1[1] = { +static arc arcs_75_1[1] = { {0, 1}, }; -static state states_73[2] = { - {2, arcs_73_0}, - {1, arcs_73_1}, +static state states_75[2] = { + {2, arcs_75_0}, + {1, arcs_75_1}, }; -static arc arcs_74_0[1] = { - {93, 1}, +static arc arcs_76_0[1] = { + {94, 1}, }; -static arc arcs_74_1[1] = { +static arc arcs_76_1[1] = { {59, 2}, }; -static arc arcs_74_2[1] = { +static arc arcs_76_2[1] = { {82, 3}, }; -static arc arcs_74_3[1] = { - {100, 4}, +static arc arcs_76_3[1] = { + {103, 4}, }; -static arc arcs_74_4[2] = { - {158, 5}, +static arc arcs_76_4[2] = { + {161, 5}, {0, 4}, }; -static arc arcs_74_5[1] = { +static arc arcs_76_5[1] = { {0, 5}, }; -static state states_74[6] = { - {1, arcs_74_0}, - {1, arcs_74_1}, - {1, arcs_74_2}, - {1, arcs_74_3}, - {2, arcs_74_4}, - {1, arcs_74_5}, +static state states_76[6] = { + {1, arcs_76_0}, + {1, arcs_76_1}, + {1, arcs_76_2}, + {1, arcs_76_3}, + {2, arcs_76_4}, + {1, arcs_76_5}, }; -static arc arcs_75_0[1] = { - {89, 1}, +static arc arcs_77_0[1] = { + {90, 1}, }; -static arc arcs_75_1[1] = { +static arc arcs_77_1[1] = { {26, 2}, }; -static arc arcs_75_2[2] = { - {158, 3}, +static arc arcs_77_2[2] = { + {161, 3}, {0, 2}, }; -static arc arcs_75_3[1] = { +static arc arcs_77_3[1] = { {0, 3}, }; -static state states_75[4] = { - {1, arcs_75_0}, - {1, arcs_75_1}, - {2, arcs_75_2}, - {1, arcs_75_3}, +static state states_77[4] = { + {1, arcs_77_0}, + {1, arcs_77_1}, + {2, arcs_77_2}, + {1, arcs_77_3}, }; -static arc arcs_76_0[2] = { - {152, 1}, - {161, 1}, +static arc arcs_78_0[2] = { + {155, 1}, + {164, 1}, }; -static arc arcs_76_1[1] = { +static arc arcs_78_1[1] = { {0, 1}, }; -static state states_76[2] = { - {2, arcs_76_0}, - {1, arcs_76_1}, +static state states_78[2] = { + {2, arcs_78_0}, + {1, arcs_78_1}, }; -static arc arcs_77_0[1] = { - {93, 1}, +static arc arcs_79_0[1] = { + {94, 1}, }; -static arc arcs_77_1[1] = { +static arc arcs_79_1[1] = { {59, 2}, }; -static arc arcs_77_2[1] = { +static arc arcs_79_2[1] = { {82, 3}, }; -static arc arcs_77_3[1] = { - {102, 4}, +static arc arcs_79_3[1] = { + {105, 4}, }; -static arc arcs_77_4[2] = { - {160, 5}, +static arc arcs_79_4[2] = { + {163, 5}, {0, 4}, }; -static arc arcs_77_5[1] = { +static arc arcs_79_5[1] = { {0, 5}, }; -static state states_77[6] = { - {1, arcs_77_0}, - {1, arcs_77_1}, - {1, arcs_77_2}, - {1, arcs_77_3}, - {2, arcs_77_4}, - {1, arcs_77_5}, +static state states_79[6] = { + {1, arcs_79_0}, + {1, arcs_79_1}, + {1, arcs_79_2}, + {1, arcs_79_3}, + {2, arcs_79_4}, + {1, arcs_79_5}, }; -static arc arcs_78_0[1] = { - {89, 1}, +static arc arcs_80_0[1] = { + {90, 1}, }; -static arc arcs_78_1[1] = { +static arc arcs_80_1[1] = { {26, 2}, }; -static arc arcs_78_2[2] = { - {160, 3}, +static arc arcs_80_2[2] = { + {163, 3}, {0, 2}, }; -static arc arcs_78_3[1] = { +static arc arcs_80_3[1] = { {0, 3}, }; -static state states_78[4] = { - {1, arcs_78_0}, - {1, arcs_78_1}, - {2, arcs_78_2}, - {1, arcs_78_3}, +static state states_80[4] = { + {1, arcs_80_0}, + {1, arcs_80_1}, + {2, arcs_80_2}, + {1, arcs_80_3}, }; -static arc arcs_79_0[1] = { +static arc arcs_81_0[1] = { {26, 1}, }; -static arc arcs_79_1[2] = { +static arc arcs_81_1[2] = { {27, 0}, {0, 1}, }; -static state states_79[2] = { - {1, arcs_79_0}, - {2, arcs_79_1}, +static state states_81[2] = { + {1, arcs_81_0}, + {2, arcs_81_1}, }; -static arc arcs_80_0[1] = { +static arc arcs_82_0[1] = { {19, 1}, }; -static arc arcs_80_1[1] = { +static arc arcs_82_1[1] = { {0, 1}, }; -static state states_80[2] = { - {1, arcs_80_0}, - {1, arcs_80_1}, +static state states_82[2] = { + {1, arcs_82_0}, + {1, arcs_82_1}, }; -static arc arcs_81_0[1] = { - {163, 1}, +static arc arcs_83_0[1] = { + {166, 1}, }; -static arc arcs_81_1[2] = { +static arc arcs_83_1[2] = { {9, 2}, {0, 1}, }; -static arc arcs_81_2[1] = { +static arc arcs_83_2[1] = { {0, 2}, }; -static state states_81[3] = { - {1, arcs_81_0}, - {2, arcs_81_1}, - {1, arcs_81_2}, +static state states_83[3] = { + {1, arcs_83_0}, + {2, arcs_83_1}, + {1, arcs_83_2}, }; -static dfa dfas[82] = { +static dfa dfas[84] = { {256, "single_input", 0, 3, states_0, - "\004\050\014\000\000\000\000\025\074\205\011\162\000\101\000\000\014\041\151\020\010"}, + "\004\050\014\000\000\000\000\025\074\205\011\344\004\010\002\000\140\010\111\203\100"}, {257, "file_input", 0, 2, states_1, - "\204\050\014\000\000\000\000\025\074\205\011\162\000\101\000\000\014\041\151\020\010"}, + "\204\050\014\000\000\000\000\025\074\205\011\344\004\010\002\000\140\010\111\203\100"}, {258, "eval_input", 0, 3, states_2, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, {259, "decorator", 0, 7, states_3, "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {260, "decorators", 0, 2, states_4, @@ -1752,13 +1804,13 @@ {265, "fplist", 0, 3, states_9, "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {266, "stmt", 0, 2, states_10, - "\000\050\014\000\000\000\000\025\074\205\011\162\000\101\000\000\014\041\151\020\010"}, + "\000\050\014\000\000\000\000\025\074\205\011\344\004\010\002\000\140\010\111\203\100"}, {267, "simple_stmt", 0, 4, states_11, - "\000\040\010\000\000\000\000\025\074\205\011\000\000\101\000\000\014\041\151\000\010"}, + "\000\040\010\000\000\000\000\025\074\205\011\000\000\010\002\000\140\010\111\003\100"}, {268, "small_stmt", 0, 2, states_12, - "\000\040\010\000\000\000\000\025\074\205\011\000\000\101\000\000\014\041\151\000\010"}, + "\000\040\010\000\000\000\000\025\074\205\011\000\000\010\002\000\140\010\111\003\100"}, {269, "expr_stmt", 0, 6, states_13, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, {270, "augassign", 0, 2, states_14, "\000\000\000\000\000\360\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {271, "print_stmt", 0, 9, states_15, @@ -1768,7 +1820,7 @@ {273, "pass_stmt", 0, 2, states_17, "\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {274, "flow_stmt", 0, 2, states_18, - "\000\000\000\000\000\000\000\000\074\000\000\000\000\000\000\000\000\000\000\000\010"}, + "\000\000\000\000\000\000\000\000\074\000\000\000\000\000\000\000\000\000\000\000\100"}, {275, "break_stmt", 0, 2, states_19, "\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000"}, {276, "continue_stmt", 0, 2, states_20, @@ -1776,7 +1828,7 @@ {277, "return_stmt", 0, 3, states_21, "\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000"}, {278, "yield_stmt", 0, 2, states_22, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\100"}, {279, "raise_stmt", 0, 7, states_23, "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000"}, {280, "import_stmt", 0, 2, states_24, @@ -1802,101 +1854,105 @@ {290, "assert_stmt", 0, 5, states_34, "\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000"}, {291, "compound_stmt", 0, 2, states_35, - "\000\010\004\000\000\000\000\000\000\000\000\162\000\000\000\000\000\000\000\020\000"}, + "\000\010\004\000\000\000\000\000\000\000\000\344\004\000\000\000\000\000\000\200\000"}, {292, "if_stmt", 0, 8, states_36, - "\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000"}, {293, "while_stmt", 0, 8, states_37, - "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\040\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"}, + "\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"}, {295, "try_stmt", 0, 13, states_39, + "\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000"}, + {296, "with_stmt", 0, 6, states_40, + "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000"}, + {297, "with_var", 0, 5, states_41, + "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {298, "except_clause", 0, 5, states_42, + "\000\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000"}, + {299, "suite", 0, 5, states_43, + "\004\040\010\000\000\000\000\025\074\205\011\000\000\010\002\000\140\010\111\003\100"}, + {300, "testlist_safe", 0, 5, states_44, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, + {301, "old_test", 0, 2, states_45, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, + {302, "old_lambdef", 0, 5, states_46, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"}, + {303, "test", 0, 6, states_47, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, + {304, "or_test", 0, 2, states_48, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\003\000"}, + {305, "and_test", 0, 2, states_49, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\003\000"}, + {306, "not_test", 0, 3, states_50, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\002\000\140\010\111\003\000"}, + {307, "comparison", 0, 2, states_51, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"}, + {308, "comp_op", 0, 4, states_52, + "\000\000\000\000\000\000\000\000\000\000\004\000\000\000\362\017\000\000\000\000\000"}, + {309, "expr", 0, 2, states_53, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"}, + {310, "xor_expr", 0, 2, states_54, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"}, + {311, "and_expr", 0, 2, states_55, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"}, + {312, "shift_expr", 0, 2, states_56, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"}, + {313, "arith_expr", 0, 2, states_57, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"}, + {314, "term", 0, 2, states_58, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"}, + {315, "factor", 0, 3, states_59, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"}, + {316, "power", 0, 4, states_60, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\111\003\000"}, + {317, "atom", 0, 11, states_61, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\111\003\000"}, + {318, "listmaker", 0, 5, states_62, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, + {319, "testlist_gexp", 0, 5, states_63, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, + {320, "lambdef", 0, 5, states_64, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000"}, + {321, "trailer", 0, 7, states_65, + "\000\040\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\001\000\000"}, + {322, "subscriptlist", 0, 3, states_66, + "\000\040\050\000\000\000\000\000\000\010\000\000\000\010\002\000\140\010\111\003\000"}, + {323, "subscript", 0, 7, states_67, + "\000\040\050\000\000\000\000\000\000\010\000\000\000\010\002\000\140\010\111\003\000"}, + {324, "sliceop", 0, 3, states_68, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + {325, "exprlist", 0, 3, states_69, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\140\010\111\003\000"}, + {326, "testlist", 0, 3, states_70, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, + {327, "dictmaker", 0, 5, states_71, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, + {328, "classdef", 0, 8, states_72, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000"}, + {329, "arglist", 0, 8, states_73, + "\000\040\010\060\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, + {330, "argument", 0, 4, states_74, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, + {331, "list_iter", 0, 2, states_75, + "\000\000\000\000\000\000\000\000\000\000\000\104\000\000\000\000\000\000\000\000\000"}, + {332, "list_for", 0, 6, states_76, "\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"}, - {297, "suite", 0, 5, states_41, - "\004\040\010\000\000\000\000\025\074\205\011\000\000\101\000\000\014\041\151\000\010"}, - {298, "testlist_safe", 0, 5, states_42, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, - {299, "old_test", 0, 2, states_43, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, - {300, "old_lambdef", 0, 5, states_44, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"}, - {301, "test", 0, 6, states_45, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, - {302, "or_test", 0, 2, states_46, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\100\000\000\014\041\151\000\000"}, - {303, "and_test", 0, 2, states_47, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\100\000\000\014\041\151\000\000"}, - {304, "not_test", 0, 3, states_48, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\100\000\000\014\041\151\000\000"}, - {305, "comparison", 0, 2, states_49, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\014\041\151\000\000"}, - {306, "comp_op", 0, 4, states_50, - "\000\000\000\000\000\000\000\000\000\000\004\000\000\100\376\001\000\000\000\000\000"}, - {307, "expr", 0, 2, states_51, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\014\041\151\000\000"}, - {308, "xor_expr", 0, 2, states_52, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\014\041\151\000\000"}, - {309, "and_expr", 0, 2, states_53, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\014\041\151\000\000"}, - {310, "shift_expr", 0, 2, states_54, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\014\041\151\000\000"}, - {311, "arith_expr", 0, 2, states_55, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\014\041\151\000\000"}, - {312, "term", 0, 2, states_56, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\014\041\151\000\000"}, - {313, "factor", 0, 3, states_57, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\014\041\151\000\000"}, - {314, "power", 0, 4, states_58, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\040\151\000\000"}, - {315, "atom", 0, 11, states_59, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\040\151\000\000"}, - {316, "listmaker", 0, 5, states_60, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, - {317, "testlist_gexp", 0, 5, states_61, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, - {318, "lambdef", 0, 5, states_62, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"}, - {319, "trailer", 0, 7, states_63, - "\000\040\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\040\000\000\000"}, - {320, "subscriptlist", 0, 3, states_64, - "\000\040\050\000\000\000\000\000\000\010\000\000\000\101\000\000\014\041\151\000\000"}, - {321, "subscript", 0, 7, states_65, - "\000\040\050\000\000\000\000\000\000\010\000\000\000\101\000\000\014\041\151\000\000"}, - {322, "sliceop", 0, 3, states_66, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {323, "exprlist", 0, 3, states_67, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\000\000\000\014\041\151\000\000"}, - {324, "testlist", 0, 3, states_68, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, - {325, "dictmaker", 0, 5, states_69, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, - {326, "classdef", 0, 8, states_70, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\020\000"}, - {327, "arglist", 0, 8, states_71, - "\000\040\010\060\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, - {328, "argument", 0, 4, states_72, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, - {329, "list_iter", 0, 2, states_73, - "\000\000\000\000\000\000\000\000\000\000\000\042\000\000\000\000\000\000\000\000\000"}, - {330, "list_for", 0, 6, states_74, - "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"}, - {331, "list_if", 0, 4, states_75, - "\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"}, - {332, "gen_iter", 0, 2, states_76, - "\000\000\000\000\000\000\000\000\000\000\000\042\000\000\000\000\000\000\000\000\000"}, - {333, "gen_for", 0, 6, states_77, - "\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"}, - {334, "gen_if", 0, 4, states_78, - "\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000"}, - {335, "testlist1", 0, 2, states_79, - "\000\040\010\000\000\000\000\000\000\000\000\000\000\101\000\000\014\041\151\000\000"}, - {336, "encoding_decl", 0, 2, states_80, + {333, "list_if", 0, 4, states_77, + "\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000"}, + {334, "gen_iter", 0, 2, states_78, + "\000\000\000\000\000\000\000\000\000\000\000\104\000\000\000\000\000\000\000\000\000"}, + {335, "gen_for", 0, 6, states_79, + "\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000"}, + {336, "gen_if", 0, 4, states_80, + "\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000"}, + {337, "testlist1", 0, 2, states_81, + "\000\040\010\000\000\000\000\000\000\000\000\000\000\010\002\000\140\010\111\003\000"}, + {338, "encoding_decl", 0, 2, states_82, "\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {337, "yield_expr", 0, 3, states_81, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\010"}, + {339, "yield_expr", 0, 3, states_83, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\100"}, }; -static label labels[164] = { +static label labels[167] = { {0, "EMPTY"}, {256, 0}, {4, 0}, @@ -1906,12 +1962,12 @@ {266, 0}, {0, 0}, {258, 0}, - {324, 0}, + {326, 0}, {259, 0}, {50, 0}, {287, 0}, {7, 0}, - {327, 0}, + {329, 0}, {8, 0}, {260, 0}, {261, 0}, @@ -1919,11 +1975,11 @@ {1, 0}, {262, 0}, {11, 0}, - {297, 0}, + {299, 0}, {263, 0}, {264, 0}, {22, 0}, - {301, 0}, + {303, 0}, {12, 0}, {16, 0}, {36, 0}, @@ -1940,7 +1996,7 @@ {289, 0}, {290, 0}, {270, 0}, - {337, 0}, + {339, 0}, {37, 0}, {38, 0}, {39, 0}, @@ -1956,7 +2012,7 @@ {1, "print"}, {35, 0}, {1, "del"}, - {323, 0}, + {325, 0}, {1, "pass"}, {275, 0}, {276, 0}, @@ -1978,38 +2034,41 @@ {284, 0}, {1, "global"}, {1, "exec"}, - {307, 0}, + {309, 0}, {1, "in"}, {1, "assert"}, {292, 0}, {293, 0}, {294, 0}, {295, 0}, - {326, 0}, + {296, 0}, + {328, 0}, {1, "if"}, {1, "elif"}, {1, "else"}, {1, "while"}, {1, "for"}, {1, "try"}, - {296, 0}, + {298, 0}, {1, "finally"}, + {1, "with"}, + {297, 0}, {1, "except"}, {5, 0}, {6, 0}, - {298, 0}, - {299, 0}, + {300, 0}, + {301, 0}, + {304, 0}, {302, 0}, - {300, 0}, {1, "lambda"}, - {318, 0}, - {303, 0}, + {320, 0}, + {305, 0}, {1, "or"}, - {304, 0}, + {306, 0}, {1, "and"}, {1, "not"}, - {305, 0}, - {306, 0}, + {307, 0}, + {308, 0}, {20, 0}, {21, 0}, {28, 0}, @@ -2018,53 +2077,53 @@ {29, 0}, {29, 0}, {1, "is"}, - {308, 0}, + {310, 0}, {18, 0}, - {309, 0}, + {311, 0}, {33, 0}, - {310, 0}, + {312, 0}, {19, 0}, - {311, 0}, + {313, 0}, {34, 0}, - {312, 0}, + {314, 0}, {14, 0}, {15, 0}, - {313, 0}, + {315, 0}, {17, 0}, {24, 0}, {48, 0}, {32, 0}, - {314, 0}, - {315, 0}, + {316, 0}, + {317, 0}, + {321, 0}, {319, 0}, - {317, 0}, {9, 0}, - {316, 0}, + {318, 0}, {10, 0}, {26, 0}, - {325, 0}, + {327, 0}, {27, 0}, {25, 0}, - {335, 0}, + {337, 0}, {2, 0}, {3, 0}, - {330, 0}, - {333, 0}, - {320, 0}, - {321, 0}, + {332, 0}, + {335, 0}, {322, 0}, + {323, 0}, + {324, 0}, {1, "class"}, - {328, 0}, - {329, 0}, + {330, 0}, {331, 0}, - {332, 0}, + {333, 0}, {334, 0}, {336, 0}, + {338, 0}, {1, "yield"}, }; grammar _PyParser_Grammar = { - 82, + 84, dfas, - {164, labels}, + {167, labels}, 256 }; Index: Python/ast.c =================================================================== --- Python/ast.c (revision 42621) +++ Python/ast.c (working copy) @@ -314,7 +314,7 @@ } } -/* Set the context ctx for expr_ty e returning 0 on success, -1 on error. +/* Set the context ctx for expr_ty e returning 1 on success, 0 on error. Only sets context for expr kinds that "can appear in assignment context" (according to ../Parser/Python.asdl). For other expr kinds, it sets @@ -339,7 +339,7 @@ a little more complex than necessary as a result. It also means that expressions in an augmented assignment have no context. Consider restructuring so that augmented assignment uses - set_context(), too + set_context(), too. */ assert(ctx != AugStore && ctx != AugLoad); @@ -2713,7 +2713,91 @@ return TryFinally(body, finally, LINENO(n), c->c_arena); } +static expr_ty +with_var_name(struct compiling *c, const node *n, int child_num) +{ + const node *child = CHILD(n, child_num); + expr_ty result; + + REQ(child, dotted_name); + if (strcmp(STR(CHILD(child, 0)), "None") == 0) { + ast_error(child, "assignment to None"); + return NULL; + } + result = ast_for_dotted_name(c, child); + return set_context(result, Store, n) ? result : NULL; +} + +static expr_ty +ast_for_with_var(struct compiling *c, const node *n) +{ + int i, first_child = 1, len = 1; /* The standard case is "as NAME" */ + asdl_seq *variables; + char *child_str; + + REQ(n, with_var); + if (strcmp(STR(CHILD(n, 0)), "as") != 0) { + ast_error(n, "expected \"with [context_expr] as [var]\""); + return NULL; + } + child_str = STR(CHILD(n, 1)); + if (child_str && (strcmp(child_str, "(") == 0)) { + /* (NCH(n) - 2) / 2: If a tuple of variables, subtract "as", "(", and + * ")" from the child count, add one back to count the first element + * of the tuple, and divide by two to eliminate "," between remaining + * elements. */ + len = (NCH(n) - 2) / 2; + assert(len > 0); /* Grammar should enforce this */ + first_child = 2; + } + else { + return with_var_name(c, n, first_child); + } + variables = asdl_seq_new(len, c->c_arena); + + if (!variables) + return NULL; + + for (i = 0; i != len; ++i) { + expr_ty variable = with_var_name(c, n, (2 * i) + first_child); + if (!variable) { + return NULL; + } + asdl_seq_SET(variables, i, variable); + } + return Tuple(variables, Store, LINENO(n), c->c_arena); +} + +/* with_stmt: 'with' test [ with_var ] ':' suite */ static stmt_ty +ast_for_with_stmt(struct compiling *c, const node *n) +{ + expr_ty context_expr, optional_vars = NULL; + int suite_index = 3; /* skip 'with', test, and ':' */ + asdl_seq *suite_seq; + + assert(TYPE(n) == with_stmt); + context_expr = ast_for_expr(c, CHILD(n, 1)); + if (TYPE(CHILD(n, 2)) == with_var) { + optional_vars = ast_for_with_var(c, CHILD(n, 2)); + + if (!optional_vars) { + return NULL; + } + if (!set_context(optional_vars, Store, n)) { + return NULL; + } + suite_index = 4; + } + + suite_seq = ast_for_suite(c, CHILD(n, suite_index)); + if (!suite_seq) { + return NULL; + } + return With(context_expr, optional_vars, suite_seq, LINENO(n), c->c_arena); +} + +static stmt_ty ast_for_classdef(struct compiling *c, const node *n) { /* classdef: 'class' NAME ['(' testlist ')'] ':' suite */ @@ -2813,6 +2897,8 @@ return ast_for_for_stmt(c, ch); case try_stmt: return ast_for_try_stmt(c, ch); + case with_stmt: + return ast_for_with_stmt(c, ch); case funcdef: return ast_for_funcdef(c, ch); case classdef: Index: Python/symtable.c =================================================================== --- Python/symtable.c (revision 42621) +++ Python/symtable.c (working copy) @@ -891,6 +891,21 @@ } static int +symtable_new_tmpname(struct symtable *st) +{ + char tmpname[256]; + identifier tmp; + + PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", + ++st->st_cur->ste_tmpname); + tmp = PyString_InternFromString(tmpname); + if (!symtable_add_def(st, tmp, DEF_LOCAL)) + return 0; + Py_DECREF(tmp); + return 1; +} + +static int symtable_visit_stmt(struct symtable *st, stmt_ty s) { switch (s->kind) { @@ -1051,6 +1066,17 @@ case Continue_kind: /* nothing to do here */ break; + case With_kind: + if (!symtable_new_tmpname(st)) + return 0; + VISIT(st, expr, s->v.With.context_expr); + if (s->v.With.optional_vars) { + if (!symtable_new_tmpname(st)) + return 0; + VISIT(st, expr, s->v.With.optional_vars); + } + VISIT_SEQ(st, stmt, s->v.With.body); + break; } return 1; } @@ -1093,26 +1119,16 @@ VISIT_SEQ(st, expr, e->v.Dict.keys); VISIT_SEQ(st, expr, e->v.Dict.values); break; - case ListComp_kind: { - char tmpname[256]; - identifier tmp; - - PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", - ++st->st_cur->ste_tmpname); - tmp = PyString_InternFromString(tmpname); - if (!symtable_add_def(st, tmp, DEF_LOCAL)) + case ListComp_kind: + if (!symtable_new_tmpname(st)) return 0; - Py_DECREF(tmp); VISIT(st, expr, e->v.ListComp.elt); VISIT_SEQ(st, comprehension, e->v.ListComp.generators); break; - } - case GeneratorExp_kind: { - if (!symtable_visit_genexp(st, e)) { + case GeneratorExp_kind: + if (!symtable_visit_genexp(st, e)) return 0; - } break; - } case Yield_kind: if (e->v.Yield.value) VISIT(st, expr, e->v.Yield.value); Index: Python/compile.c =================================================================== --- Python/compile.c (revision 42621) +++ Python/compile.c (working copy) @@ -191,6 +191,8 @@ static int inplace_binop(struct compiler *, operator_ty); static int expr_constant(expr_ty e); +static int compiler_with(struct compiler *, stmt_ty); + static PyCodeObject *assemble(struct compiler *, int addNone); static PyObject *__doc__; @@ -289,6 +291,7 @@ error: compiler_free(&c); + assert(!PyErr_Occurred()); return co; } @@ -1157,6 +1160,18 @@ } +/* Allocate a new "anonymous" local variable. + Used by list comprehensions and with statements. +*/ + +static PyObject * +compiler_new_tmpname(struct compiler *c) +{ + char tmpname[256]; + PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->u->u_tmpname); + return PyString_FromString(tmpname); +} + /* Allocate a new block and return a pointer to it. Returns NULL on error. */ @@ -1360,7 +1375,8 @@ return -1; case BREAK_LOOP: return 0; - + case WITH_CLEANUP: + return 3; case LOAD_LOCALS: return 1; case RETURN_VALUE: @@ -2663,6 +2679,8 @@ break; case Continue_kind: return compiler_continue(c); + case With_kind: + return compiler_with(c, s); } return 1; } @@ -3124,7 +3142,6 @@ static int compiler_listcomp(struct compiler *c, expr_ty e) { - char tmpname[256]; identifier tmp; int rc = 0; static identifier append; @@ -3136,8 +3153,7 @@ if (!append) return 0; } - PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->u->u_tmpname); - tmp = PyString_FromString(tmpname); + tmp = compiler_new_tmpname(c); if (!tmp) return 0; ADDOP_I(c, BUILD_LIST, 0); @@ -3291,7 +3307,149 @@ } } +/* + Implements the with statement from PEP 343. + + The semantics outlined in that PEP are as follows: + + with EXPR as VAR: + BLOCK + + It is implemented roughly as: + + context = (EXPR).__context__() + exit = context.__exit__ # not calling it + value = context.__enter__() + try: + VAR = value # if VAR present in the syntax + BLOCK + finally: + if an exception was raised: + exc = copy of (exception, instance, traceback) + else: + exc = (None, None, None) + exit(*exc) + */ static int +compiler_with(struct compiler *c, stmt_ty s) +{ + static identifier context_attr, enter_attr, exit_attr; + basicblock *block, *finally; + identifier tmpexit, tmpvalue = NULL; + + assert(s->kind == With_kind); + + if (!context_attr) { + context_attr = PyString_InternFromString("__context__"); + if (!context_attr) + return 0; + } + if (!enter_attr) { + enter_attr = PyString_InternFromString("__enter__"); + if (!enter_attr) + return 0; + } + if (!exit_attr) { + exit_attr = PyString_InternFromString("__exit__"); + if (!exit_attr) + return 0; + } + + block = compiler_new_block(c); + finally = compiler_new_block(c); + if (!block || !finally) + return 0; + + /* Create a temporary variable to hold context.__exit__ */ + tmpexit = compiler_new_tmpname(c); + if (tmpexit == NULL) + return 0; + PyArena_AddPyObject(c->c_arena, tmpexit); + + if (s->v.With.optional_vars) { + /* Create a temporary variable to hold context.__enter__(). + We need to do this rather than preserving it on the stack + because SETUP_FINALLY remembers the stack level. + We need to do the assignment *inside* the try/finally + so that context.__exit__() is called when the assignment + fails. But we need to call context.__enter__() *before* + the try/finally so that if it fails we won't call + context.__exit__(). + */ + tmpvalue = compiler_new_tmpname(c); + if (tmpvalue == NULL) + return 0; + PyArena_AddPyObject(c->c_arena, tmpvalue); + } + + /* Evaluate (EXPR).__context__() */ + VISIT(c, expr, s->v.With.context_expr); + ADDOP_O(c, LOAD_ATTR, context_attr, names); + ADDOP_I(c, CALL_FUNCTION, 0); + + /* Squirrel away context.__exit__ */ + ADDOP(c, DUP_TOP); + ADDOP_O(c, LOAD_ATTR, exit_attr, names); + if (!compiler_nameop(c, tmpexit, Store)) + return 0; + + /* Call context.__enter__() */ + ADDOP_O(c, LOAD_ATTR, enter_attr, names); + ADDOP_I(c, CALL_FUNCTION, 0); + + if (s->v.With.optional_vars) { + /* Store it in tmpvalue */ + if (!compiler_nameop(c, tmpvalue, Store)) + return 0; + } + else { + /* Discard result from context.__enter__() */ + ADDOP(c, POP_TOP); + } + + /* Start the try block */ + ADDOP_JREL(c, SETUP_FINALLY, finally); + + compiler_use_next_block(c, block); + if (!compiler_push_fblock(c, FINALLY_TRY, block)) { + return 0; + } + + if (s->v.With.optional_vars) { + /* Bind saved result of context.__enter__() to VAR */ + if (!compiler_nameop(c, tmpvalue, Load) || + !compiler_nameop(c, tmpvalue, Del)) + return 0; + VISIT(c, expr, s->v.With.optional_vars); + } + + /* BLOCK code */ + VISIT_SEQ(c, stmt, s->v.With.body); + + /* End of try block; start the finally block */ + ADDOP(c, POP_BLOCK); + compiler_pop_fblock(c, FINALLY_TRY, block); + + ADDOP_O(c, LOAD_CONST, Py_None, consts); + compiler_use_next_block(c, finally); + if (!compiler_push_fblock(c, FINALLY_END, finally)) + return 0; + + /* Finally block starts; push tmpexit and issue our magic opcode. */ + if (!compiler_nameop(c, tmpexit, Load) || + !compiler_nameop(c, tmpexit, Del)) + return 0; + ADDOP(c, WITH_CLEANUP); + ADDOP_I(c, CALL_FUNCTION, 3); + ADDOP(c, POP_TOP); + + /* Finally block ends. */ + ADDOP(c, END_FINALLY); + compiler_pop_fblock(c, FINALLY_END, finally); + return 1; +} + +static int compiler_visit_expr(struct compiler *c, expr_ty e) { int i, n; Index: Python/Python-ast.c =================================================================== --- Python/Python-ast.c (revision 42621) +++ Python/Python-ast.c (working copy) @@ -84,6 +84,12 @@ "body", "orelse", }; +PyTypeObject *With_type; +char *With_fields[]={ + "context_expr", + "optional_vars", + "body", +}; PyTypeObject *Raise_type; char *Raise_fields[]={ "type", @@ -465,6 +471,8 @@ if (!While_type) return 0; If_type = make_type("If", stmt_type, If_fields, 3); if (!If_type) return 0; + With_type = make_type("With", stmt_type, With_fields, 3); + if (!With_type) return 0; Raise_type = make_type("Raise", stmt_type, Raise_fields, 3); if (!Raise_type) return 0; TryExcept_type = make_type("TryExcept", stmt_type, TryExcept_fields, 3); @@ -1000,6 +1008,29 @@ } stmt_ty +With(expr_ty context_expr, expr_ty optional_vars, asdl_seq * body, int lineno, + PyArena *arena) +{ + stmt_ty p; + if (!context_expr) { + PyErr_SetString(PyExc_ValueError, + "field context_expr is required for With"); + return NULL; + } + p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) { + PyErr_NoMemory(); + return NULL; + } + p->kind = With_kind; + p->v.With.context_expr = context_expr; + p->v.With.optional_vars = optional_vars; + p->v.With.body = body; + p->lineno = lineno; + return p; +} + +stmt_ty Raise(expr_ty type, expr_ty inst, expr_ty tback, int lineno, PyArena *arena) { stmt_ty p; @@ -2062,6 +2093,26 @@ goto failed; Py_DECREF(value); break; + case With_kind: + result = PyType_GenericNew(With_type, NULL, NULL); + if (!result) goto failed; + value = ast2obj_expr(o->v.With.context_expr); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "context_expr", value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(o->v.With.optional_vars); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "optional_vars", value) == + -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(o->v.With.body, ast2obj_stmt); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "body", value) == -1) + goto failed; + Py_DECREF(value); + break; case Raise_kind: result = PyType_GenericNew(Raise_type, NULL, NULL); if (!result) goto failed; @@ -2922,6 +2973,7 @@ if(PyDict_SetItemString(d, "For", (PyObject*)For_type) < 0) return; if(PyDict_SetItemString(d, "While", (PyObject*)While_type) < 0) return; if(PyDict_SetItemString(d, "If", (PyObject*)If_type) < 0) return; + if(PyDict_SetItemString(d, "With", (PyObject*)With_type) < 0) return; if(PyDict_SetItemString(d, "Raise", (PyObject*)Raise_type) < 0) return; if(PyDict_SetItemString(d, "TryExcept", (PyObject*)TryExcept_type) < 0) return; Index: Include/opcode.h =================================================================== --- Include/opcode.h (revision 42621) +++ Include/opcode.h (working copy) @@ -72,13 +72,12 @@ #define INPLACE_XOR 78 #define INPLACE_OR 79 #define BREAK_LOOP 80 - +#define WITH_CLEANUP 81 #define LOAD_LOCALS 82 #define RETURN_VALUE 83 #define IMPORT_STAR 84 #define EXEC_STMT 85 #define YIELD_VALUE 86 - #define POP_BLOCK 87 #define END_FINALLY 88 #define BUILD_CLASS 89 Index: Include/graminit.h =================================================================== --- Include/graminit.h (revision 42621) +++ Include/graminit.h (working copy) @@ -38,45 +38,47 @@ #define while_stmt 293 #define for_stmt 294 #define try_stmt 295 -#define except_clause 296 -#define suite 297 -#define testlist_safe 298 -#define old_test 299 -#define old_lambdef 300 -#define test 301 -#define or_test 302 -#define and_test 303 -#define not_test 304 -#define comparison 305 -#define comp_op 306 -#define expr 307 -#define xor_expr 308 -#define and_expr 309 -#define shift_expr 310 -#define arith_expr 311 -#define term 312 -#define factor 313 -#define power 314 -#define atom 315 -#define listmaker 316 -#define testlist_gexp 317 -#define lambdef 318 -#define trailer 319 -#define subscriptlist 320 -#define subscript 321 -#define sliceop 322 -#define exprlist 323 -#define testlist 324 -#define dictmaker 325 -#define classdef 326 -#define arglist 327 -#define argument 328 -#define list_iter 329 -#define list_for 330 -#define list_if 331 -#define gen_iter 332 -#define gen_for 333 -#define gen_if 334 -#define testlist1 335 -#define encoding_decl 336 -#define yield_expr 337 +#define with_stmt 296 +#define with_var 297 +#define except_clause 298 +#define suite 299 +#define testlist_safe 300 +#define old_test 301 +#define old_lambdef 302 +#define test 303 +#define or_test 304 +#define and_test 305 +#define not_test 306 +#define comparison 307 +#define comp_op 308 +#define expr 309 +#define xor_expr 310 +#define and_expr 311 +#define shift_expr 312 +#define arith_expr 313 +#define term 314 +#define factor 315 +#define power 316 +#define atom 317 +#define listmaker 318 +#define testlist_gexp 319 +#define lambdef 320 +#define trailer 321 +#define subscriptlist 322 +#define subscript 323 +#define sliceop 324 +#define exprlist 325 +#define testlist 326 +#define dictmaker 327 +#define classdef 328 +#define arglist 329 +#define argument 330 +#define list_iter 331 +#define list_for 332 +#define list_if 333 +#define gen_iter 334 +#define gen_for 335 +#define gen_if 336 +#define testlist1 337 +#define encoding_decl 338 +#define yield_expr 339 Index: Include/Python-ast.h =================================================================== --- Include/Python-ast.h (revision 42621) +++ Include/Python-ast.h (working copy) @@ -61,11 +61,11 @@ struct _stmt { enum { FunctionDef_kind=1, ClassDef_kind=2, Return_kind=3, Delete_kind=4, Assign_kind=5, AugAssign_kind=6, Print_kind=7, - For_kind=8, While_kind=9, If_kind=10, Raise_kind=11, - TryExcept_kind=12, TryFinally_kind=13, Assert_kind=14, - Import_kind=15, ImportFrom_kind=16, Exec_kind=17, - Global_kind=18, Expr_kind=19, Pass_kind=20, Break_kind=21, - Continue_kind=22 } kind; + For_kind=8, While_kind=9, If_kind=10, With_kind=11, + Raise_kind=12, TryExcept_kind=13, TryFinally_kind=14, + Assert_kind=15, Import_kind=16, ImportFrom_kind=17, + Exec_kind=18, Global_kind=19, Expr_kind=20, Pass_kind=21, + Break_kind=22, Continue_kind=23 } kind; union { struct { identifier name; @@ -125,6 +125,12 @@ } If; struct { + expr_ty context_expr; + expr_ty optional_vars; + asdl_seq *body; + } With; + + struct { expr_ty type; expr_ty inst; expr_ty tback; @@ -355,6 +361,8 @@ PyArena *arena); stmt_ty If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, PyArena *arena); +stmt_ty With(expr_ty context_expr, expr_ty optional_vars, asdl_seq * body, int + lineno, PyArena *arena); stmt_ty Raise(expr_ty type, expr_ty inst, expr_ty tback, int lineno, PyArena *arena); stmt_ty TryExcept(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, int Index: Grammar/Grammar =================================================================== --- Grammar/Grammar (revision 42621) +++ Grammar/Grammar (working copy) @@ -70,7 +70,7 @@ exec_stmt: 'exec' expr ['in' test [',' test]] assert_stmt: 'assert' test [',' test] -compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef +compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef 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] @@ -79,6 +79,8 @@ ['else' ':' suite] ['finally' ':' suite] | 'finally' ':' suite)) +with_stmt: 'with' test [ with_var ] ':' suite +with_var: NAME (dotted_name | '(' dotted_name (',' dotted_name)* ')') # NB compile.c makes sure that the default except clause is last except_clause: 'except' [test [',' test]] suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT Index: Misc/ACKS =================================================================== --- Misc/ACKS (revision 42621) +++ Misc/ACKS (working copy) @@ -62,6 +62,7 @@ Philippe Biondi Stuart Bishop Roy Bixler +Mike Bland Martin Bless Pablo Bleyer Erik van Blokland Index: Misc/NEWS =================================================================== --- Misc/NEWS (revision 42621) +++ Misc/NEWS (working copy) @@ -19,6 +19,8 @@ - dict.__getitem__ now looks for a __missing__ hook before raising KeyError. +- PEP 343: with statement implemented. + - Fix the encodings package codec search function to only search inside its own package. Fixes problem reported in patch #1433198. Index: Parser/Python.asdl =================================================================== --- Parser/Python.asdl (revision 42621) +++ Parser/Python.asdl (working copy) @@ -25,6 +25,7 @@ | For(expr target, expr iter, stmt* body, stmt* orelse) | While(expr test, stmt* body, stmt* orelse) | If(expr test, stmt* body, stmt* orelse) + | With(expr context_expr, expr? optional_vars, stmt* body) -- 'type' is a bad name | Raise(expr? type, expr? inst, expr? tback) Index: Tools/compiler/ast.txt =================================================================== --- Tools/compiler/ast.txt (revision 42621) +++ Tools/compiler/ast.txt (working copy) @@ -20,6 +20,7 @@ Continue: For: assign, list, body, else_& While: test, body, else_& +With: expr, vars&, body If: tests!, else_& Exec: expr, locals&, globals& From: modname*, names* @@ -42,7 +43,7 @@ ListComp: expr, quals! ListCompFor: assign, list, ifs! ListCompIf: test -GenExpr: code +GenExpr: code GenExprInner: expr, quals! GenExprFor: assign, iter, ifs! GenExprIf: test Index: Doc/lib/asttable.tex =================================================================== --- Doc/lib/asttable.tex (revision 42621) +++ Doc/lib/asttable.tex (working copy) @@ -272,6 +272,11 @@ \lineiii{}{\member{else_}}{} \hline +\lineiii{With}{\member{expr}}{} +\lineiii{}{\member{vars&}}{} +\lineiii{}{\member{body}}{} +\hline + \lineiii{Yield}{\member{value}}{} \hline Index: Doc/ref/ref7.tex =================================================================== --- Doc/ref/ref7.tex (revision 42621) +++ Doc/ref/ref7.tex (working copy) @@ -308,6 +308,12 @@ statement to generate exceptions may be found in section~\ref{raise}. +\section{The \keyword{with} statement\label{with}} +\stindex{with} + +The \keyword{with} statement specifies + + \section{Function definitions\label{function}} \indexii{function}{definition} \stindex{def} Index: Lib/symbol.py =================================================================== --- Lib/symbol.py (revision 42621) +++ Lib/symbol.py (working copy) @@ -50,48 +50,50 @@ while_stmt = 293 for_stmt = 294 try_stmt = 295 -except_clause = 296 -suite = 297 -testlist_safe = 298 -old_test = 299 -old_lambdef = 300 -test = 301 -or_test = 302 -and_test = 303 -not_test = 304 -comparison = 305 -comp_op = 306 -expr = 307 -xor_expr = 308 -and_expr = 309 -shift_expr = 310 -arith_expr = 311 -term = 312 -factor = 313 -power = 314 -atom = 315 -listmaker = 316 -testlist_gexp = 317 -lambdef = 318 -trailer = 319 -subscriptlist = 320 -subscript = 321 -sliceop = 322 -exprlist = 323 -testlist = 324 -dictmaker = 325 -classdef = 326 -arglist = 327 -argument = 328 -list_iter = 329 -list_for = 330 -list_if = 331 -gen_iter = 332 -gen_for = 333 -gen_if = 334 -testlist1 = 335 -encoding_decl = 336 -yield_expr = 337 +with_stmt = 296 +with_var = 297 +except_clause = 298 +suite = 299 +testlist_safe = 300 +old_test = 301 +old_lambdef = 302 +test = 303 +or_test = 304 +and_test = 305 +not_test = 306 +comparison = 307 +comp_op = 308 +expr = 309 +xor_expr = 310 +and_expr = 311 +shift_expr = 312 +arith_expr = 313 +term = 314 +factor = 315 +power = 316 +atom = 317 +listmaker = 318 +testlist_gexp = 319 +lambdef = 320 +trailer = 321 +subscriptlist = 322 +subscript = 323 +sliceop = 324 +exprlist = 325 +testlist = 326 +dictmaker = 327 +classdef = 328 +arglist = 329 +argument = 330 +list_iter = 331 +list_for = 332 +list_if = 333 +gen_iter = 334 +gen_for = 335 +gen_if = 336 +testlist1 = 337 +encoding_decl = 338 +yield_expr = 339 #--end constants-- sym_name = {} Index: Lib/compiler/ast.py =================================================================== --- Lib/compiler/ast.py (revision 42621) +++ Lib/compiler/ast.py (working copy) @@ -553,9 +553,9 @@ self.varargs = 1 if flags & CO_VARKEYWORDS: self.kwargs = 1 + - def getChildren(self): children = [] children.append(self.decorators) @@ -584,9 +584,9 @@ self.lineno = lineno self.argnames = ['[outmost-iterable]'] self.varargs = self.kwargs = None + - def getChildren(self): return self.code, @@ -763,9 +763,9 @@ self.varargs = 1 if flags & CO_VARKEYWORDS: self.kwargs = 1 + - def getChildren(self): children = [] children.append(self.argnames) @@ -1297,6 +1297,31 @@ def __repr__(self): return "While(%s, %s, %s)" % (repr(self.test), repr(self.body), repr(self.else_)) +class With(Node): + def __init__(self, expr, vars, body, lineno=None): + self.expr = expr + self.vars = vars + self.body = body + self.lineno = lineno + + def getChildren(self): + children = [] + children.append(self.expr) + children.append(self.vars) + children.append(self.body) + return tuple(children) + + def getChildNodes(self): + nodelist = [] + nodelist.append(self.expr) + if self.vars is not None: + nodelist.append(self.vars) + nodelist.append(self.body) + return tuple(nodelist) + + def __repr__(self): + return "With(%s, %s, %s)" % (repr(self.expr), repr(self.vars), repr(self.body)) + class Yield(Node): def __init__(self, value, lineno=None): self.value = value Index: Lib/opcode.py =================================================================== --- Lib/opcode.py (revision 42621) +++ Lib/opcode.py (working copy) @@ -41,6 +41,7 @@ hasjabs.append(op) # Instruction opcodes for compiled code +# Blank lines correspond to available opcodes def_op('STOP_CODE', 0) def_op('POP_TOP', 1) @@ -59,7 +60,6 @@ def_op('LIST_APPEND', 18) def_op('BINARY_POWER', 19) - def_op('BINARY_MULTIPLY', 20) def_op('BINARY_DIVIDE', 21) def_op('BINARY_MODULO', 22) @@ -70,7 +70,6 @@ def_op('BINARY_TRUE_DIVIDE', 27) def_op('INPLACE_FLOOR_DIVIDE', 28) def_op('INPLACE_TRUE_DIVIDE', 29) - def_op('SLICE+0', 30) def_op('SLICE+1', 31) def_op('SLICE+2', 32) @@ -93,7 +92,6 @@ def_op('INPLACE_MODULO', 59) def_op('STORE_SUBSCR', 60) def_op('DELETE_SUBSCR', 61) - def_op('BINARY_LSHIFT', 62) def_op('BINARY_RSHIFT', 63) def_op('BINARY_AND', 64) @@ -113,13 +111,12 @@ def_op('INPLACE_XOR', 78) def_op('INPLACE_OR', 79) def_op('BREAK_LOOP', 80) - +def_op('WITH_CLEANUP', 81) def_op('LOAD_LOCALS', 82) def_op('RETURN_VALUE', 83) def_op('IMPORT_STAR', 84) def_op('EXEC_STMT', 85) def_op('YIELD_VALUE', 86) - def_op('POP_BLOCK', 87) def_op('END_FINALLY', 88) def_op('BUILD_CLASS', 89) @@ -171,7 +168,6 @@ def_op('CALL_FUNCTION', 131) # #args + (#kwargs << 8) def_op('MAKE_FUNCTION', 132) # Number of args with default values def_op('BUILD_SLICE', 133) # Number of items - def_op('MAKE_CLOSURE', 134) def_op('LOAD_CLOSURE', 135) hasfree.append(135) @@ -183,7 +179,6 @@ def_op('CALL_FUNCTION_VAR', 140) # #args + (#kwargs << 8) def_op('CALL_FUNCTION_KW', 141) # #args + (#kwargs << 8) def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8) - def_op('EXTENDED_ARG', 143) EXTENDED_ARG = 143 Index: Lib/test/nested.py =================================================================== --- Lib/test/nested.py (revision 0) +++ Lib/test/nested.py (revision 0) @@ -0,0 +1,41 @@ +import sys +from collections import deque + + +class nested(object): + def __init__(self, *contexts): + self.contexts = contexts + self.entered = None + + def __context__(self): + return self + + def __enter__(self): + if self.entered is not None: + raise RuntimeError("Context is not reentrant") + self.entered = deque() + vars = [] + try: + for context in self.contexts: + mgr = context.__context__() + vars.append(mgr.__enter__()) + self.entered.appendleft(mgr) + except: + self.__exit__(*sys.exc_info()) + raise + return vars + + def __exit__(self, *exc_info): + # Behave like nested with statements + # first in, last out + # New exceptions override old ones + ex = exc_info + for mgr in self.entered: + try: + mgr.__exit__(*ex) + except: + ex = sys.exc_info() + self.entered = None + if ex is not exc_info: + raise ex[0], ex[1], ex[2] + Index: Lib/test/test_with.py =================================================================== --- Lib/test/test_with.py (revision 0) +++ Lib/test/test_with.py (revision 0) @@ -0,0 +1,523 @@ +#!/usr/bin/env python + +''' +Tests for the with statement specified in PEP 343. +''' + +__author__ = "Mike Bland" +__email__ = "mbland at acm dot org" +__version__ = "" + +import unittest +from contextmanager import GeneratorContextManager +from nested import nested +from test.test_support import run_unittest + + +class MockContextManager(GeneratorContextManager): + def __init__(self, gen): + GeneratorContextManager.__init__(self, gen) + self.context_called = False + self.enter_called = False + self.exit_called = False + self.exit_args = None + + def __context__(self): + self.context_called = True + return GeneratorContextManager.__context__(self) + + def __enter__(self): + self.enter_called = True + return GeneratorContextManager.__enter__(self) + + def __exit__(self, type, value, traceback): + self.exit_called = True + self.exit_args = (type, value, traceback) + return GeneratorContextManager.__exit__(self, type, value, traceback) + + +def mock_contextmanager(func): + def helper(*args, **kwds): + return MockContextManager(func(*args, **kwds)) + return helper + + +class MockResource(object): + def __init__(self): + self.yielded = False + self.stopped = False + + +@mock_contextmanager +def mock_contextmanager_generator(): + mock = MockResource() + try: + mock.yielded = True + yield mock + finally: + mock.stopped = True + + +class MockNested(nested): + def __init__(self, *contexts): + nested.__init__(self, *contexts) + self.context_called = False + self.enter_called = False + self.exit_called = False + self.exit_args = None + + def __context__(self): + self.context_called = True + return nested.__context__(self) + + def __enter__(self): + self.enter_called = True + return nested.__enter__(self) + + def __exit__(self, *exc_info): + self.exit_called = True + self.exit_args = exc_info + return nested.__exit__(self, *exc_info) + + +class FailureTestCase(unittest.TestCase): + def testNameError(self): + def fooNotDeclared(): + with foo: pass + self.assertRaises(NameError, fooNotDeclared) + + def testContextAttributeError(self): + class LacksContext(object): + def __enter__(self): + pass + + def __exit__(self, type, value, traceback): + pass + + def fooLacksContext(): + foo = LacksContext() + with foo: pass + self.assertRaises(AttributeError, fooLacksContext) + + def testEnterAttributeError(self): + class LacksEnter(object): + def __context__(self): + pass + + def __exit__(self, type, value, traceback): + pass + + def fooLacksEnter(): + foo = LacksEnter() + with foo: pass + self.assertRaises(AttributeError, fooLacksEnter) + + def testExitAttributeError(self): + class LacksExit(object): + def __context__(self): + pass + + def __enter__(self): + pass + + def fooLacksExit(): + foo = LacksExit() + with foo: pass + self.assertRaises(AttributeError, fooLacksExit) + + def assertRaisesSyntaxError(self, codestr): + def shouldRaiseSyntaxError(s): + compile(s, '', 'single') + self.assertRaises(SyntaxError, shouldRaiseSyntaxError, codestr) + + def testAssignmentToNoneError(self): + self.assertRaisesSyntaxError('with mock as None:\n pass') + self.assertRaisesSyntaxError( + 'with mock as (None):\n' + ' pass') + + def testAssignmentToEmptyTupleError(self): + self.assertRaisesSyntaxError( + 'with mock as ():\n' + ' pass') + + def testAssignmentToTupleOnlyContainingNoneError(self): + self.assertRaisesSyntaxError('with mock as None,:\n pass') + self.assertRaisesSyntaxError( + 'with mock as (None,):\n' + ' pass') + + def testAssignmentToTupleContainingNoneError(self): + self.assertRaisesSyntaxError( + 'with mock as (foo, None, bar):\n' + ' pass') + + def testContextThrows(self): + class ContextThrows(object): + def __context__(self): + raise RuntimeError("Context threw") + + def shouldThrow(): + ct = ContextThrows() + self.foo = None + with ct as self.foo: + pass + self.assertRaises(RuntimeError, shouldThrow) + self.assertEqual(self.foo, None) + + def testEnterThrows(self): + class EnterThrows(object): + def __context__(self): + return self + + def __enter__(self): + raise RuntimeError("Context threw") + + def __exit__(self, *args): + pass + + def shouldThrow(): + ct = EnterThrows() + self.foo = None + with ct as self.foo: + pass + self.assertRaises(RuntimeError, shouldThrow) + self.assertEqual(self.foo, None) + + def testExitThrows(self): + class ExitThrows(object): + def __context__(self): + return self + def __enter__(self): + return + def __exit__(self, *args): + raise RuntimeError(42) + def shouldThrow(): + with ExitThrows(): + pass + self.assertRaises(RuntimeError, shouldThrow) + +class ContextmanagerAssertionMixin(object): + TEST_EXCEPTION = RuntimeError("test exception") + + def assertInWithManagerInvariants(self, mock_manager): + self.assertTrue(mock_manager.context_called) + self.assertTrue(mock_manager.enter_called) + self.assertFalse(mock_manager.exit_called) + self.assertEqual(mock_manager.exit_args, None) + + def assertAfterWithManagerInvariants(self, mock_manager, exit_args): + self.assertTrue(mock_manager.context_called) + self.assertTrue(mock_manager.enter_called) + self.assertTrue(mock_manager.exit_called) + self.assertEqual(mock_manager.exit_args, exit_args) + + def assertAfterWithManagerInvariantsNoError(self, mock_manager): + self.assertAfterWithManagerInvariants(mock_manager, + (None, None, None)) + + def assertInWithGeneratorInvariants(self, mock_generator): + self.assertTrue(mock_generator.yielded) + self.assertFalse(mock_generator.stopped) + + def assertAfterWithGeneratorInvariantsNoError(self, mock_generator): + self.assertTrue(mock_generator.yielded) + self.assertTrue(mock_generator.stopped) + + def raiseTestException(self): + raise self.TEST_EXCEPTION + + def assertAfterWithManagerInvariantsWithError(self, mock_manager): + self.assertTrue(mock_manager.context_called) + self.assertTrue(mock_manager.enter_called) + self.assertTrue(mock_manager.exit_called) + self.assertEqual(mock_manager.exit_args[0], RuntimeError) + self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION) + + def assertAfterWithGeneratorInvariantsWithError(self, mock_generator): + self.assertTrue(mock_generator.yielded) + self.assertTrue(mock_generator.stopped) + + +class NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin): + def testInlineGeneratorSyntax(self): + with mock_contextmanager_generator(): + pass + + def testUnboundGenerator(self): + mock = mock_contextmanager_generator() + with mock: + pass + self.assertAfterWithManagerInvariantsNoError(mock) + + def testInlineGeneratorBoundSyntax(self): + with mock_contextmanager_generator() as foo: + self.assertInWithGeneratorInvariants(foo) + # FIXME: In the future, we'll try to keep the bound names from leaking + self.assertAfterWithGeneratorInvariantsNoError(foo) + + def testInlineGeneratorBoundToExistingVariable(self): + foo = None + with mock_contextmanager_generator() as foo: + self.assertInWithGeneratorInvariants(foo) + self.assertAfterWithGeneratorInvariantsNoError(foo) + + def testInlineGeneratorBoundToDottedVariable(self): + with mock_contextmanager_generator() as self.foo: + self.assertInWithGeneratorInvariants(self.foo) + self.assertAfterWithGeneratorInvariantsNoError(self.foo) + + def testBoundGenerator(self): + mock = mock_contextmanager_generator() + with mock as foo: + self.assertInWithGeneratorInvariants(foo) + self.assertInWithManagerInvariants(mock) + self.assertAfterWithGeneratorInvariantsNoError(foo) + self.assertAfterWithManagerInvariantsNoError(mock) + + def testNestedSingleStatements(self): + mock_a = mock_contextmanager_generator() + with mock_a as foo: + mock_b = mock_contextmanager_generator() + with mock_b as bar: + self.assertInWithManagerInvariants(mock_a) + self.assertInWithManagerInvariants(mock_b) + self.assertInWithGeneratorInvariants(foo) + self.assertInWithGeneratorInvariants(bar) + self.assertAfterWithManagerInvariantsNoError(mock_b) + self.assertAfterWithGeneratorInvariantsNoError(bar) + self.assertInWithManagerInvariants(mock_a) + self.assertInWithGeneratorInvariants(foo) + self.assertAfterWithManagerInvariantsNoError(mock_a) + self.assertAfterWithGeneratorInvariantsNoError(foo) + + +class NestedNonexceptionalTestCase(unittest.TestCase, + ContextmanagerAssertionMixin): + def testSingleArgInlineGeneratorSyntax(self): + with nested(mock_contextmanager_generator()): + pass + + def testSingleArgUnbound(self): + mock_contextmanager = mock_contextmanager_generator() + mock_nested = MockNested(mock_contextmanager) + with mock_nested: + self.assertInWithManagerInvariants(mock_contextmanager) + self.assertInWithManagerInvariants(mock_nested) + self.assertAfterWithManagerInvariantsNoError(mock_contextmanager) + self.assertAfterWithManagerInvariantsNoError(mock_nested) + + def testSingleArgBoundToNonTuple(self): + m = mock_contextmanager_generator() + # This will bind all the arguments to nested() into a single list + # assigned to foo. + with nested(m) as foo: + self.assertInWithManagerInvariants(m) + self.assertAfterWithManagerInvariantsNoError(m) + + def testSingleArgBoundToSingleElementParenthesizedList(self): + m = mock_contextmanager_generator() + # This will bind all the arguments to nested() into a single list + # assigned to foo. + # FIXME: what should this do: with nested(m) as (foo,): + with nested(m) as (foo): + self.assertInWithManagerInvariants(m) + self.assertAfterWithManagerInvariantsNoError(m) + + def testSingleArgBoundToMultipleElementTupleError(self): + def shouldThrowValueError(): + with nested(mock_contextmanager_generator()) as (foo, bar): + pass + self.assertRaises(ValueError, shouldThrowValueError) + + def testSingleArgUnbound(self): + mock_contextmanager = mock_contextmanager_generator() + mock_nested = MockNested(mock_contextmanager) + with mock_nested: + self.assertInWithManagerInvariants(mock_contextmanager) + self.assertInWithManagerInvariants(mock_nested) + self.assertAfterWithManagerInvariantsNoError(mock_contextmanager) + self.assertAfterWithManagerInvariantsNoError(mock_nested) + + def testMultipleArgUnbound(self): + m = mock_contextmanager_generator() + n = mock_contextmanager_generator() + o = mock_contextmanager_generator() + mock_nested = MockNested(m, n, o) + with mock_nested: + self.assertInWithManagerInvariants(m) + self.assertInWithManagerInvariants(n) + self.assertInWithManagerInvariants(o) + self.assertInWithManagerInvariants(mock_nested) + self.assertAfterWithManagerInvariantsNoError(m) + self.assertAfterWithManagerInvariantsNoError(n) + self.assertAfterWithManagerInvariantsNoError(o) + self.assertAfterWithManagerInvariantsNoError(mock_nested) + + def testMultipleArgBound(self): + mock_nested = MockNested(mock_contextmanager_generator(), + mock_contextmanager_generator(), mock_contextmanager_generator()) + with mock_nested as (m, n, o): + self.assertInWithGeneratorInvariants(m) + self.assertInWithGeneratorInvariants(n) + self.assertInWithGeneratorInvariants(o) + self.assertInWithManagerInvariants(mock_nested) + self.assertAfterWithGeneratorInvariantsNoError(m) + self.assertAfterWithGeneratorInvariantsNoError(n) + self.assertAfterWithGeneratorInvariantsNoError(o) + self.assertAfterWithManagerInvariantsNoError(mock_nested) + + +class ExceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin): + def testSingleResource(self): + cm = mock_contextmanager_generator() + def shouldThrow(): + with cm as self.resource: + self.assertInWithManagerInvariants(cm) + self.assertInWithGeneratorInvariants(self.resource) + self.raiseTestException() + self.assertRaises(RuntimeError, shouldThrow) + self.assertAfterWithManagerInvariantsWithError(cm) + self.assertAfterWithGeneratorInvariantsWithError(self.resource) + + def testNestedSingleStatements(self): + mock_a = mock_contextmanager_generator() + mock_b = mock_contextmanager_generator() + def shouldThrow(): + with mock_a as self.foo: + with mock_b as self.bar: + self.assertInWithManagerInvariants(mock_a) + self.assertInWithManagerInvariants(mock_b) + self.assertInWithGeneratorInvariants(self.foo) + self.assertInWithGeneratorInvariants(self.bar) + self.raiseTestException() + self.assertRaises(RuntimeError, shouldThrow) + self.assertAfterWithManagerInvariantsWithError(mock_a) + self.assertAfterWithManagerInvariantsWithError(mock_b) + self.assertAfterWithGeneratorInvariantsWithError(self.foo) + self.assertAfterWithGeneratorInvariantsWithError(self.bar) + + def testMultipleResourcesInSingleStatement(self): + cm_a = mock_contextmanager_generator() + cm_b = mock_contextmanager_generator() + mock_nested = MockNested(cm_a, cm_b) + def shouldThrow(): + with mock_nested as (self.resource_a, self.resource_b): + self.assertInWithManagerInvariants(cm_a) + self.assertInWithManagerInvariants(cm_b) + self.assertInWithManagerInvariants(mock_nested) + self.assertInWithGeneratorInvariants(self.resource_a) + self.assertInWithGeneratorInvariants(self.resource_b) + self.raiseTestException() + self.assertRaises(RuntimeError, shouldThrow) + self.assertAfterWithManagerInvariantsWithError(cm_a) + self.assertAfterWithManagerInvariantsWithError(cm_b) + self.assertAfterWithManagerInvariantsWithError(mock_nested) + self.assertAfterWithGeneratorInvariantsWithError(self.resource_a) + self.assertAfterWithGeneratorInvariantsWithError(self.resource_b) + + def testNestedExceptionBeforeInnerStatement(self): + mock_a = mock_contextmanager_generator() + mock_b = mock_contextmanager_generator() + self.bar = None + def shouldThrow(): + with mock_a as self.foo: + self.assertInWithManagerInvariants(mock_a) + self.assertInWithGeneratorInvariants(self.foo) + self.raiseTestException() + with mock_b as self.bar: + pass + self.assertRaises(RuntimeError, shouldThrow) + self.assertAfterWithManagerInvariantsWithError(mock_a) + self.assertAfterWithGeneratorInvariantsWithError(self.foo) + + # The inner statement stuff should never have been touched + self.assertEqual(self.bar, None) + self.assertFalse(mock_b.context_called) + self.assertFalse(mock_b.enter_called) + self.assertFalse(mock_b.exit_called) + self.assertEqual(mock_b.exit_args, None) + + def testNestedExceptionAfterInnerStatement(self): + mock_a = mock_contextmanager_generator() + mock_b = mock_contextmanager_generator() + def shouldThrow(): + with mock_a as self.foo: + with mock_b as self.bar: + self.assertInWithManagerInvariants(mock_a) + self.assertInWithManagerInvariants(mock_b) + self.assertInWithGeneratorInvariants(self.foo) + self.assertInWithGeneratorInvariants(self.bar) + self.raiseTestException() + self.assertRaises(RuntimeError, shouldThrow) + self.assertAfterWithManagerInvariantsWithError(mock_a) + self.assertAfterWithManagerInvariantsNoError(mock_b) + self.assertAfterWithGeneratorInvariantsWithError(self.foo) + self.assertAfterWithGeneratorInvariantsNoError(self.bar) + + +class NonLocalFlowControlTestCase(unittest.TestCase): + + def testWithBreak(self): + counter = 0 + while True: + counter += 1 + with mock_contextmanager_generator(): + counter += 10 + break + counter += 100 # Not reached + self.assertEqual(counter, 11) + + def testWithContinue(self): + counter = 0 + while True: + counter += 1 + if counter > 2: + break + with mock_contextmanager_generator(): + counter += 10 + continue + counter += 100 # Not reached + self.assertEqual(counter, 12) + + def testWithReturn(self): + def foo(): + counter = 0 + while True: + counter += 1 + with mock_contextmanager_generator(): + counter += 10 + return counter + counter += 100 # Not reached + self.assertEqual(foo(), 11) + + def testWithYield(self): + def gen(): + with mock_contextmanager_generator(): + yield 12 + yield 13 + x = list(gen()) + self.assertEqual(x, [12, 13]) + + def testWithRaise(self): + counter = 0 + try: + counter += 1 + with mock_contextmanager_generator(): + counter += 10 + raise RuntimeError + counter += 100 # Not reached + except RuntimeError: + self.assertEqual(counter, 11) + else: + self.fail("Didn't raise RuntimeError") + + +def test_main(): + run_unittest(FailureTestCase, NonexceptionalTestCase, + NestedNonexceptionalTestCase, ExceptionalTestCase, + NonLocalFlowControlTestCase) + + +if __name__ == '__main__': + test_main() Index: Lib/test/contextmanager.py =================================================================== --- Lib/test/contextmanager.py (revision 0) +++ Lib/test/contextmanager.py (revision 0) @@ -0,0 +1,34 @@ +class GeneratorContextManager(object): + def __init__(self, gen): + self.gen = gen + + def __context__(self): + return self + + def __enter__(self): + try: + return self.gen.next() + except StopIteration: + raise RuntimeError("generator didn't yield") + + def __exit__(self, type, value, traceback): + if type is None: + try: + self.gen.next() + except StopIteration: + return + else: + raise RuntimeError("generator didn't stop") + else: + try: + self.gen.throw(type, value, traceback) + except (type, StopIteration): + return + else: + raise RuntimeError("generator caught exception") + +def contextmanager(func): + def helper(*args, **kwds): + return GeneratorContextManager(func(*args, **kwds)) + return helper +