Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-104770: Let generator.close() return value#104771

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
gvanrossum merged 9 commits intopython:mainfromntessore:generator-close-return
May 23, 2023
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletionsDoc/reference/expressions.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -595,12 +595,19 @@ is already executing raises a :exc:`ValueError` exception.
.. method:: generator.close()

Raises a :exc:`GeneratorExit` at the point where the generator function was
paused. If the generator function then exits gracefully, is already closed,
or raises :exc:`GeneratorExit` (by not catching the exception), close
returns to its caller. If the generator yields a value, a
:exc:`RuntimeError` is raised. If the generator raises any other exception,
it is propagated to the caller. :meth:`close` does nothing if the generator
has already exited due to an exception or normal exit.
paused. If the generator function catches the exception and returns a
value, this value is returned from :meth:`close`. If the generator function
is already closed, or raises :exc:`GeneratorExit` (by not catching the
exception), :meth:`close` returns :const:`None`. If the generator yields a
value, a :exc:`RuntimeError` is raised. If the generator raises any other
exception, it is propagated to the caller. If the generator has already
exited due to an exception or normal exit, :meth:`close` returns
:const:`None` and has no other effect.

.. versionchanged:: 3.13

If a generator returns a value upon being closed, the value is returned
by :meth:`close`.

.. index:: single: yield; examples

Expand Down
82 changes: 82 additions & 0 deletionsLib/test/test_generators.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -451,6 +451,88 @@ def g():
self.assertEqual(cm.exception.value.value, 2)


class GeneratorCloseTest(unittest.TestCase):

def test_close_no_return_value(self):
def f():
yield

gen = f()
gen.send(None)
self.assertIsNone(gen.close())

def test_close_return_value(self):
def f():
try:
yield
# close() raises GeneratorExit here, which is caught
except GeneratorExit:
return 0

gen = f()
gen.send(None)
self.assertEqual(gen.close(), 0)

def test_close_not_catching_exit(self):
def f():
yield
# close() raises GeneratorExit here, which isn't caught and
# therefore propagates -- no return value
return 0

gen = f()
gen.send(None)
self.assertIsNone(gen.close())

def test_close_not_started(self):
def f():
try:
yield
except GeneratorExit:
return 0

gen = f()
self.assertIsNone(gen.close())

def test_close_exhausted(self):
def f():
try:
yield
except GeneratorExit:
return 0

gen = f()
next(gen)
with self.assertRaises(StopIteration):
next(gen)
self.assertIsNone(gen.close())

def test_close_closed(self):
def f():
try:
yield
except GeneratorExit:
return 0

gen = f()
gen.send(None)
self.assertEqual(gen.close(), 0)
self.assertIsNone(gen.close())

def test_close_raises(self):
def f():
try:
yield
except GeneratorExit:
pass
raise RuntimeError

gen = f()
gen.send(None)
with self.assertRaises(RuntimeError):
gen.close()


class GeneratorThrowTest(unittest.TestCase):

def test_exception_context_with_yield(self):
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
If a generator returns a value upon being closed, the value is now returned
by :meth:`generator.close`.
11 changes: 8 additions & 3 deletionsObjects/genobject.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -408,11 +408,16 @@ gen_close(PyGenObject *gen, PyObject *args)
PyErr_SetString(PyExc_RuntimeError, msg);
return NULL;
}
if (PyErr_ExceptionMatches(PyExc_StopIteration)
||PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
PyErr_Clear(); /* ignorethese errors */
assert(PyErr_Occurred());
if (PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
PyErr_Clear(); /* ignorethis error */
Py_RETURN_NONE;
}
/* if the generator returned a value while closing, StopIteration was
* raised in gen_send_ex() above; retrieve and return the value here */
if (_PyGen_FetchStopIterationValue(&retval) == 0) {
return retval;
}
return NULL;
}

Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp