bpo-40890: Add `mapping` property to dict views (GH-20749)

diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 1bb8cfd..48e96a0 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -4122,6 +4122,23 @@
     return (PyObject *)dv;
 }
 
+static PyObject *
+dictview_mapping(PyObject *view)
+{
+    assert(view != NULL);
+    assert(PyDictKeys_Check(view)
+           || PyDictValues_Check(view)
+           || PyDictItems_Check(view));
+    PyObject *mapping = (PyObject *)((_PyDictViewObject *)view)->dv_dict;
+    return PyDictProxy_New(mapping);
+}
+
+static PyGetSetDef dictview_getset[] = {
+    {"mapping", (getter)dictview_mapping, (setter)NULL,
+     "dictionary that this view refers to", NULL},
+    {0}
+};
+
 /* TODO(guido): The views objects are not complete:
 
  * support more set operations
@@ -4635,7 +4652,7 @@
     (getiterfunc)dictkeys_iter,                 /* tp_iter */
     0,                                          /* tp_iternext */
     dictkeys_methods,                           /* tp_methods */
-    0,
+    .tp_getset = dictview_getset,
 };
 
 static PyObject *
@@ -4741,7 +4758,7 @@
     (getiterfunc)dictitems_iter,                /* tp_iter */
     0,                                          /* tp_iternext */
     dictitems_methods,                          /* tp_methods */
-    0,
+    .tp_getset = dictview_getset,
 };
 
 static PyObject *
@@ -4822,7 +4839,7 @@
     (getiterfunc)dictvalues_iter,               /* tp_iter */
     0,                                          /* tp_iternext */
     dictvalues_methods,                         /* tp_methods */
-    0,
+    .tp_getset = dictview_getset,
 };
 
 static PyObject *