diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -103,16 +103,37 @@ class GeneratorTest(unittest.TestCase): # unnamed generator gen = (x for x in range(10)) self.assertEqual(gen.__name__, "") self.assertEqual(gen.__qualname__, "GeneratorTest.test_name..") + def test_repr(self): + def func(): + yield 1 + self.assertIn('(generator)', repr(func)) + + def func2(f): + def function(x): + return f(x) + return function + + def func3(i): + yield i + + def func4(f): + def function(x): + yield f(x) + return function + self.assertIn('(closure)', repr(func2(func3))) + self.assertIsNotNone(func2(func3)) + self.assertIn('(closure,generator)', repr(func4(func3))) + class ExceptionTest(unittest.TestCase): # Tests for the issue #23353: check that the currently handled exception # is correctly saved/restored in PyEval_EvalFrameEx(). def test_except_throw(self): def store_raise_exc_generator(): try: diff --git a/Objects/funcobject.c b/Objects/funcobject.c --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -561,21 +561,39 @@ func_dealloc(PyFunctionObject *op) Py_XDECREF(op->func_doc); Py_XDECREF(op->func_dict); Py_XDECREF(op->func_closure); Py_XDECREF(op->func_annotations); Py_XDECREF(op->func_qualname); PyObject_GC_Del(op); } +static char* +func_get_status(PyFunctionObject *op) +{ + char *result; + PyCodeObject *co; + co = func_get_code(op); + if (co->co_flags & CO_GENERATOR && op->func_closure != NULL) + result = " (closure,generator)"; + else if (co->co_flags & CO_GENERATOR) + result = " (generator)"; + else if (op->func_closure != NULL) + result = " (closure)"; + else + result = ""; + Py_DECREF(co); + return result; +} + static PyObject* func_repr(PyFunctionObject *op) { - return PyUnicode_FromFormat("", - op->func_qualname, op); + return PyUnicode_FromFormat("", + op->func_qualname, op, func_get_status(op)); } static int func_traverse(PyFunctionObject *f, visitproc visit, void *arg) { Py_VISIT(f->func_code); Py_VISIT(f->func_globals); Py_VISIT(f->func_module);