diff -r 23ab1197df0b Lib/contextlib.py --- a/Lib/contextlib.py Wed Nov 19 13:21:40 2014 +0200 +++ b/Lib/contextlib.py Thu Nov 20 16:47:59 2014 +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 23ab1197df0b Lib/difflib.py --- a/Lib/difflib.py Wed Nov 19 13:21:40 2014 +0200 +++ b/Lib/difflib.py Thu Nov 20 16:47:59 2014 +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 23ab1197df0b Lib/ipaddress.py --- a/Lib/ipaddress.py Wed Nov 19 13:21:40 2014 +0200 +++ b/Lib/ipaddress.py Thu Nov 20 16:47:59 2014 +1100 @@ -808,7 +808,7 @@ other.broadcast_address <= self.broadcast_address): raise ValueError('%s not contained in %s' % (other, self)) if other == self: - raise StopIteration + return # Nothing to yield. # Make sure we're comparing the network of other. other = other.__class__('%s/%s' % (other.network_address, diff -r 23ab1197df0b Lib/mailbox.py --- a/Lib/mailbox.py Wed Nov 19 13:21:40 2014 +0200 +++ b/Lib/mailbox.py Thu Nov 20 16:47:59 2014 +1100 @@ -1949,7 +1949,7 @@ while True: line = self.readline() if not line: - raise StopIteration + return yield line def tell(self): diff -r 23ab1197df0b Lib/test/test_buffer.py --- a/Lib/test/test_buffer.py Wed Nov 19 13:21:40 2014 +0200 +++ b/Lib/test/test_buffer.py Thu Nov 20 16:47:59 2014 +1100 @@ -216,7 +216,7 @@ for t in iter_mode(nitems, testobj): yield t if testobj != 'ndarray': - raise StopIteration + return yield struct_items(nitems, testobj) diff -r 23ab1197df0b Objects/genobject.c --- a/Objects/genobject.c Wed Nov 19 13:21:40 2014 +0200 +++ b/Objects/genobject.c Thu Nov 20 16:47:59 2014 +1100 @@ -130,6 +130,23 @@ } 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); + Py_DECREF(exc); + Py_XDECREF(tb); + PyErr_SetString(PyExc_RuntimeError, + "generator raised StopIteration"); + PyErr_Fetch(&exc, &val2, &tb); + PyErr_NormalizeException(&exc, &val2, &tb); + PyException_SetContext(val2, val); + PyErr_Restore(exc, val2, tb); + } + } if (!result || f->f_stacktop == NULL) { /* generator can't be rerun, so release the frame */