- PEP 3106: dict.iterkeys(), .iteritems(), .itervalues() are now gone;
  and .keys(), .items(), .values() return dict views.

The dict views aren't fully functional yet; in particular, they can't
be compared to sets yet.  but they are useful as "iterator wells".

There are still 27 failing unit tests; I expect that many of these
have fairly trivial fixes, but there are so many, I could use help.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 8405782..4e5838f 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1657,6 +1657,54 @@
 	return 0;
 }
 
+PyObject *
+PyMapping_Keys(PyObject *o)
+{
+	PyObject *keys;
+	PyObject *fast;
+
+	if (PyDict_CheckExact(o))
+		return PyDict_Keys(o);
+	keys = PyObject_CallMethod(o, "keys", NULL);
+	if (keys == NULL)
+		return NULL;
+	fast = PySequence_Fast(keys, "o.keys() are not iterable");
+	Py_DECREF(keys);
+	return fast;
+}
+
+PyObject *
+PyMapping_Items(PyObject *o)
+{
+	PyObject *items;
+	PyObject *fast;
+
+	if (PyDict_CheckExact(o))
+		return PyDict_Items(o);
+	items = PyObject_CallMethod(o, "items", NULL);
+	if (items == NULL)
+		return NULL;
+	fast = PySequence_Fast(items, "o.items() are not iterable");
+	Py_DECREF(items);
+	return fast;
+}
+
+PyObject *
+PyMapping_Values(PyObject *o)
+{
+	PyObject *values;
+	PyObject *fast;
+
+	if (PyDict_CheckExact(o))
+		return PyDict_Values(o);
+	values = PyObject_CallMethod(o, "values", NULL);
+	if (values == NULL)
+		return NULL;
+	fast = PySequence_Fast(values, "o.values() are not iterable");
+	Py_DECREF(values);
+	return fast;
+}
+
 /* Operations on callable objects */
 
 /* XXX PyCallable_Check() is in object.c */
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index ec14fcb..49907b4 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1760,6 +1760,7 @@
 extern PyTypeObject PyDictIterItem_Type; /* Forward */
 static PyObject *dictiter_new(dictobject *, PyTypeObject *);
 
+#if 0
 static PyObject *
 dict_iterkeys(dictobject *dict)
 {
@@ -1777,6 +1778,7 @@
 {
 	return dictiter_new(dict, &PyDictIterItem_Type);
 }
+#endif
 
 
 PyDoc_STRVAR(contains__doc__,
@@ -1798,6 +1800,7 @@
 "D.popitem() -> (k, v), remove and return some (key, value) pair as a\n\
 2-tuple; but raise KeyError if D is empty");
 
+#if 0
 PyDoc_STRVAR(keys__doc__,
 "D.keys() -> list of D's keys");
 
@@ -1806,6 +1809,7 @@
 
 PyDoc_STRVAR(values__doc__,
 "D.values() -> list of D's values");
+#endif
 
 PyDoc_STRVAR(update__doc__,
 "D.update(E, **F) -> None.  Update D from E and F: for k in E: D[k] = E[k]\
@@ -1821,6 +1825,7 @@
 PyDoc_STRVAR(copy__doc__,
 "D.copy() -> a shallow copy of D");
 
+#if 0
 PyDoc_STRVAR(iterkeys__doc__,
 "D.iterkeys() -> an iterator over the keys of D");
 
@@ -1829,6 +1834,7 @@
 
 PyDoc_STRVAR(iteritems__doc__,
 "D.iteritems() -> an iterator over the (key, value) items of D");
+#endif
 
 /* Forward */
 static PyObject *dictkeys_new(PyObject *);
@@ -1852,18 +1858,20 @@
 	 pop__doc__},
 	{"popitem",	(PyCFunction)dict_popitem,	METH_NOARGS,
 	 popitem__doc__},
+#if 0
 	{"keys",	(PyCFunction)dict_keys,		METH_NOARGS,
 	keys__doc__},
-	{"KEYS",	(PyCFunction)dictkeys_new,	METH_NOARGS,
-	KEYS__doc__},
-	{"ITEMS",	(PyCFunction)dictitems_new,	METH_NOARGS,
-	ITEMS__doc__},
-	{"VALUES",	(PyCFunction)dictvalues_new,	METH_NOARGS,
-	VALUES__doc__},
 	{"items",	(PyCFunction)dict_items,	METH_NOARGS,
 	 items__doc__},
 	{"values",	(PyCFunction)dict_values,	METH_NOARGS,
 	 values__doc__},
+#endif
+	{"keys",	(PyCFunction)dictkeys_new,	METH_NOARGS,
+	KEYS__doc__},
+	{"items",	(PyCFunction)dictitems_new,	METH_NOARGS,
+	ITEMS__doc__},
+	{"values",	(PyCFunction)dictvalues_new,	METH_NOARGS,
+	VALUES__doc__},
 	{"update",	(PyCFunction)dict_update,	METH_VARARGS | METH_KEYWORDS,
 	 update__doc__},
 	{"fromkeys",	(PyCFunction)dict_fromkeys,	METH_VARARGS | METH_CLASS,
@@ -1872,12 +1880,14 @@
 	 clear__doc__},
 	{"copy",	(PyCFunction)dict_copy,		METH_NOARGS,
 	 copy__doc__},
+#if 0
 	{"iterkeys",	(PyCFunction)dict_iterkeys,	METH_NOARGS,
 	 iterkeys__doc__},
 	{"itervalues",	(PyCFunction)dict_itervalues,	METH_NOARGS,
 	 itervalues__doc__},
 	{"iteritems",	(PyCFunction)dict_iteritems,	METH_NOARGS,
 	 iteritems__doc__},
+#endif
 	{NULL,		NULL}	/* sentinel */
 };
 
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index f716906..cd211e6 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -2601,7 +2601,11 @@
 		Py_INCREF(dictitems);
 	}
 	else {
-		dictitems = PyObject_CallMethod(obj, "iteritems", "");
+		PyObject *items = PyObject_CallMethod(obj, "items", "");
+		if (items == NULL)
+			goto end;
+		dictitems = PyObject_GetIter(items);
+		Py_DECREF(items);
 		if (dictitems == NULL)
 			goto end;
 	}