Issue #21205: Add a new ``__qualname__`` attribute to generator, the qualified
name, and use it in the representation of a generator (``repr(gen)``). The
default name of the generator (``__name__`` attribute) is now get from the
function instead of the code. Use ``gen.gi_code.co_name`` to get the name of
the code.
diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst
index 21408f4..2830936 100644
--- a/Doc/library/inspect.rst
+++ b/Doc/library/inspect.rst
@@ -159,6 +159,16 @@
 |           |                 | arguments and local       |
 |           |                 | variables                 |
 +-----------+-----------------+---------------------------+
+| generator | __name__        | name                      |
++-----------+-----------------+---------------------------+
+|           | __qualname__    | qualified name            |
++-----------+-----------------+---------------------------+
+|           | gi_frame        | frame                     |
++-----------+-----------------+---------------------------+
+|           | gi_running      | is the generator running? |
++-----------+-----------------+---------------------------+
+|           | gi_code         | code                      |
++-----------+-----------------+---------------------------+
 | builtin   | __doc__         | documentation string      |
 +-----------+-----------------+---------------------------+
 |           | __name__        | original name of this     |
@@ -169,6 +179,10 @@
 |           |                 | ``None``                  |
 +-----------+-----------------+---------------------------+
 
+.. versionchanged:: 3.5
+
+   Add ``__qualname__`` attribute to generators.
+
 
 .. function:: getmembers(object[, predicate])
 
diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst
index b5536ad..17b703a 100644
--- a/Doc/whatsnew/3.5.rst
+++ b/Doc/whatsnew/3.5.rst
@@ -304,6 +304,12 @@
   or :exc:`ssl.SSLWantWriteError` on a non-blocking socket if the operation
   would block. Previously, it would return 0.  See :issue:`20951`.
 
+* The ``__name__`` attribute of generator is now set from the function name,
+  instead of being set from the code name. Use ``gen.gi_code.co_name`` to
+  retrieve the code name. Generators also have a new ``__qualname__``
+  attribute, the qualified name, which is now used for the representation
+  of a generator (``repr(gen)``). See :issue:`21205`.
+
 Changes in the C API
 --------------------
 
diff --git a/Include/genobject.h b/Include/genobject.h
index 65f1ecf..23571e6 100644
--- a/Include/genobject.h
+++ b/Include/genobject.h
@@ -25,6 +25,12 @@
 
     /* List of weak reference. */
     PyObject *gi_weakreflist;
+
+    /* Name of the generator. */
+    PyObject *gi_name;
+
+    /* Qualified name of the generator. */
+    PyObject *gi_qualname;
 } PyGenObject;
 
 PyAPI_DATA(PyTypeObject) PyGen_Type;
@@ -33,6 +39,8 @@
 #define PyGen_CheckExact(op) (Py_TYPE(op) == &PyGen_Type)
 
 PyAPI_FUNC(PyObject *) PyGen_New(struct _frame *);
+PyAPI_FUNC(PyObject *) PyGen_NewWithQualName(struct _frame *,
+    PyObject *name, PyObject *qualname);
 PyAPI_FUNC(int) PyGen_NeedsFinalizing(PyGenObject *);
 PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **);
 PyObject *_PyGen_Send(PyGenObject *, PyObject *);
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index 91afe47..3882f4c 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -50,6 +50,45 @@
         self.assertEqual(gc.garbage, old_garbage)
 
 
+class GeneratorTest(unittest.TestCase):
+
+    def test_name(self):
+        def func():
+            yield 1
+
+        # check generator names
+        gen = func()
+        self.assertEqual(gen.__name__, "func")
+        self.assertEqual(gen.__qualname__,
+                         "GeneratorTest.test_name.<locals>.func")
+
+        # modify generator names
+        gen.__name__ = "name"
+        gen.__qualname__ = "qualname"
+        self.assertEqual(gen.__name__, "name")
+        self.assertEqual(gen.__qualname__, "qualname")
+
+        # generator names must be a string and cannot be deleted
+        self.assertRaises(TypeError, setattr, gen, '__name__', 123)
+        self.assertRaises(TypeError, setattr, gen, '__qualname__', 123)
+        self.assertRaises(TypeError, delattr, gen, '__name__')
+        self.assertRaises(TypeError, delattr, gen, '__qualname__')
+
+        # modify names of the function creating the generator
+        func.__qualname__ = "func_qualname"
+        func.__name__ = "func_name"
+        gen = func()
+        self.assertEqual(gen.__name__, "func_name")
+        self.assertEqual(gen.__qualname__, "func_qualname")
+
+        # unnamed generator
+        gen = (x for x in range(10))
+        self.assertEqual(gen.__name__,
+                         "<genexpr>")
+        self.assertEqual(gen.__qualname__,
+                         "GeneratorTest.test_name.<locals>.<genexpr>")
+
+
 tutorial_tests = """
 Let's try a simple generator:
 
diff --git a/Misc/NEWS b/Misc/NEWS
index 892ce76..9cf7065 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,12 @@
 Core and Builtins
 -----------------
 
+- Issue #21205: Add a new ``__qualname__`` attribute to generator, the
+  qualified name, and use it in the representation of a generator
+  (``repr(gen)``). The default name of the generator (``__name__`` attribute)
+  is now get from the function instead of the code. Use ``gen.gi_code.co_name``
+  to get the name of the code.
+
 - Issue #21669: With the aid of heuristics in SyntaxError.__init__, the
   parser now attempts to generate more meaningful (or at least more search
   engine friendly) error messages when "exec" and "print" are used as
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 08d30bf..831b15d 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -12,6 +12,8 @@
 {
     Py_VISIT((PyObject *)gen->gi_frame);
     Py_VISIT(gen->gi_code);
+    Py_VISIT(gen->gi_name);
+    Py_VISIT(gen->gi_qualname);
     return 0;
 }
 
@@ -58,6 +60,8 @@
     _PyObject_GC_UNTRACK(self);
     Py_CLEAR(gen->gi_frame);
     Py_CLEAR(gen->gi_code);
+    Py_CLEAR(gen->gi_name);
+    Py_CLEAR(gen->gi_qualname);
     PyObject_GC_Del(gen);
 }
 
@@ -418,33 +422,73 @@
 gen_repr(PyGenObject *gen)
 {
     return PyUnicode_FromFormat("<generator object %S at %p>",
-                                ((PyCodeObject *)gen->gi_code)->co_name,
-                                gen);
+                                gen->gi_qualname, gen);
 }
 
-
 static PyObject *
-gen_get_name(PyGenObject *gen)
+gen_get_name(PyGenObject *op)
 {
-    PyObject *name = ((PyCodeObject *)gen->gi_code)->co_name;
-    Py_INCREF(name);
-    return name;
+    Py_INCREF(op->gi_name);
+    return op->gi_name;
 }
 
+static int
+gen_set_name(PyGenObject *op, PyObject *value)
+{
+    PyObject *tmp;
 
-PyDoc_STRVAR(gen__name__doc__,
-"Return the name of the generator's associated code object.");
+    /* Not legal to del gen.gi_name or to set it to anything
+     * other than a string object. */
+    if (value == NULL || !PyUnicode_Check(value)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "__name__ must be set to a string object");
+        return -1;
+    }
+    tmp = op->gi_name;
+    Py_INCREF(value);
+    op->gi_name = value;
+    Py_DECREF(tmp);
+    return 0;
+}
+
+static PyObject *
+gen_get_qualname(PyGenObject *op)
+{
+    Py_INCREF(op->gi_qualname);
+    return op->gi_qualname;
+}
+
+static int
+gen_set_qualname(PyGenObject *op, PyObject *value)
+{
+    PyObject *tmp;
+
+    /* Not legal to del gen.__qualname__ or to set it to anything
+     * other than a string object. */
+    if (value == NULL || !PyUnicode_Check(value)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "__qualname__ must be set to a string object");
+        return -1;
+    }
+    tmp = op->gi_qualname;
+    Py_INCREF(value);
+    op->gi_qualname = value;
+    Py_DECREF(tmp);
+    return 0;
+}
 
 static PyGetSetDef gen_getsetlist[] = {
-    {"__name__", (getter)gen_get_name, NULL, gen__name__doc__},
-    {NULL}
+    {"__name__", (getter)gen_get_name, (setter)gen_set_name,
+     PyDoc_STR("name of the generator")},
+    {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
+     PyDoc_STR("qualified name of the generator")},
+    {NULL} /* Sentinel */
 };
 
-
 static PyMemberDef gen_memberlist[] = {
-    {"gi_frame",        T_OBJECT, offsetof(PyGenObject, gi_frame),      READONLY},
-    {"gi_running",      T_BOOL,    offsetof(PyGenObject, gi_running),    READONLY},
-    {"gi_code",     T_OBJECT, offsetof(PyGenObject, gi_code),  READONLY},
+    {"gi_frame",     T_OBJECT, offsetof(PyGenObject, gi_frame),    READONLY},
+    {"gi_running",   T_BOOL,   offsetof(PyGenObject, gi_running),  READONLY},
+    {"gi_code",      T_OBJECT, offsetof(PyGenObject, gi_code),     READONLY},
     {NULL}      /* Sentinel */
 };
 
@@ -510,7 +554,7 @@
 };
 
 PyObject *
-PyGen_New(PyFrameObject *f)
+PyGen_NewWithQualName(PyFrameObject *f, PyObject *name, PyObject *qualname)
 {
     PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type);
     if (gen == NULL) {
@@ -523,10 +567,26 @@
     gen->gi_code = (PyObject *)(f->f_code);
     gen->gi_running = 0;
     gen->gi_weakreflist = NULL;
+    if (name != NULL)
+        gen->gi_name = name;
+    else
+        gen->gi_name = ((PyCodeObject *)gen->gi_code)->co_name;
+    Py_INCREF(gen->gi_name);
+    if (qualname != NULL)
+        gen->gi_qualname = qualname;
+    else
+        gen->gi_qualname = gen->gi_name;
+    Py_INCREF(gen->gi_qualname);
     _PyObject_GC_TRACK(gen);
     return (PyObject *)gen;
 }
 
+PyObject *
+PyGen_New(PyFrameObject *f)
+{
+    return PyGen_NewWithQualName(f, NULL, NULL);
+}
+
 int
 PyGen_NeedsFinalizing(PyGenObject *gen)
 {
diff --git a/Python/ceval.c b/Python/ceval.c
index e14e772..3ede055 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3401,10 +3401,11 @@
    PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust
    the test in the if statements in Misc/gdbinit (pystack and pystackv). */
 
-PyObject *
-PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
+static PyObject *
+_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
            PyObject **args, int argcount, PyObject **kws, int kwcount,
-           PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
+           PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure,
+           PyObject *name, PyObject *qualname)
 {
     PyCodeObject* co = (PyCodeObject*)_co;
     PyFrameObject *f;
@@ -3596,7 +3597,7 @@
 
         /* Create a new generator that owns the ready to run frame
          * and return that as the value. */
-        return PyGen_New(f);
+        return PyGen_NewWithQualName(f, name, qualname);
     }
 
     retval = PyEval_EvalFrameEx(f,0);
@@ -3615,6 +3616,16 @@
     return retval;
 }
 
+PyObject *
+PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
+           PyObject **args, int argcount, PyObject **kws, int kwcount,
+           PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
+{
+    return _PyEval_EvalCodeWithName(_co, globals, locals,
+                                    args, argcount, kws, kwcount,
+                                    defs, defcount, kwdefs, closure,
+                                    NULL, NULL);
+}
 
 static PyObject *
 special_lookup(PyObject *o, _Py_Identifier *id)
@@ -4313,6 +4324,8 @@
     PyObject *globals = PyFunction_GET_GLOBALS(func);
     PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
     PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func);
+    PyObject *name = ((PyFunctionObject *)func) -> func_name;
+    PyObject *qualname = ((PyFunctionObject *)func) -> func_qualname;
     PyObject **d = NULL;
     int nd = 0;
 
@@ -4355,10 +4368,11 @@
         d = &PyTuple_GET_ITEM(argdefs, 0);
         nd = Py_SIZE(argdefs);
     }
-    return PyEval_EvalCodeEx((PyObject*)co, globals,
-                             (PyObject *)NULL, (*pp_stack)-n, na,
-                             (*pp_stack)-2*nk, nk, d, nd, kwdefs,
-                             PyFunction_GET_CLOSURE(func));
+    return _PyEval_EvalCodeWithName((PyObject*)co, globals,
+                                    (PyObject *)NULL, (*pp_stack)-n, na,
+                                    (*pp_stack)-2*nk, nk, d, nd, kwdefs,
+                                    PyFunction_GET_CLOSURE(func),
+                                    name, qualname);
 }
 
 static PyObject *