diff -r 20a5a56ce090 Lib/contextlib.py --- a/Lib/contextlib.py Wed Jan 07 13:14:47 2015 +1000 +++ b/Lib/contextlib.py Thu Jan 08 21:37:01 2015 +1100 @@ -81,6 +81,11 @@ # was passed to throw(). This prevents a StopIteration # raised inside the "with" statement from being suppressed return exc is not value + except RuntimeError as exc: + # Likewise, suppress if that StopException got wrapped up. + if exc.__context__ is value: + return False + raise except: # only re-raise if it's *not* the exception that was # passed to throw(), because __exit__() must not raise diff -r 20a5a56ce090 Lib/difflib.py --- a/Lib/difflib.py Wed Jan 07 13:14:47 2015 +1000 +++ b/Lib/difflib.py Thu Jan 08 21:37:01 2015 +1100 @@ -1516,6 +1516,7 @@ yield from_line,to_line,True def _line_pair_iterator(): + try: """Yields from/to lines of text with a change indication. This function is an iterator. It itself pulls lines from the line @@ -1542,19 +1543,21 @@ from_line, fromDiff = fromlines.pop(0) to_line, to_diff = tolines.pop(0) yield (from_line,to_line,fromDiff or to_diff) + except StopIteration: + pass # Stop when done # Handle case where user does not want context differencing, just yield # them up without doing anything else with them. line_pair_iterator = _line_pair_iterator() if context is None: - while True: - yield next(line_pair_iterator) + yield from line_pair_iterator # Handle case where user wants context differencing. We must do some # storage of lines until we know for sure that they are to be yielded. else: context += 1 lines_to_write = 0 - while True: + try: + while True: # Store lines up until we find a difference, note use of a # circular queue because we only need to keep around what # we need for context. @@ -1588,6 +1591,8 @@ else: lines_to_write -= 1 yield from_line, to_line, found_diff + except StopIteration: + return # When the helper terminates, end. _file_template = """ diff -r 20a5a56ce090 Objects/genobject.c --- a/Objects/genobject.c Wed Jan 07 13:14:47 2015 +1000 +++ b/Objects/genobject.c Thu Jan 08 21:37:01 2015 +1100 @@ -130,6 +130,26 @@ } Py_CLEAR(result); } + else if (!result) + { + if (PyErr_ExceptionMatches(PyExc_StopIteration)) + { + PyObject *exc, *val, *val2, *tb; + PyErr_Fetch(&exc, &val, &tb); + PyErr_NormalizeException(&exc, &val, &tb); + if (tb != NULL) { + PyException_SetTraceback(val, tb); + } + Py_DECREF(exc); + Py_XDECREF(tb); + PyErr_SetString(PyExc_RuntimeError, + "generator raised StopIteration"); + PyErr_Fetch(&exc, &val2, &tb); + PyErr_NormalizeException(&exc, &val2, &tb); + PyException_SetCause(val2, val); + PyErr_Restore(exc, val2, tb); + } + } if (!result || f->f_stacktop == NULL) { /* generator can't be rerun, so release the frame */