@@ -1808,8 +1808,8 @@ PyDoc_STRVAR(values__doc__,
18081808"D.values() -> list of D's values" );
18091809
18101810PyDoc_STRVAR (update__doc__ ,
1811- "D.update(E, **F) -> None. Update D from E and F: for k in E: D[k] = E[k]\n\
1812- (if E has keys else: for (k, v) in E: D[k] = v) then: for k in F: D[k] = F[k]" );
1811+ "D.update(E, **F) -> None. Update D from E and F: for k in E: D[k] = E[k]\
1812+ \n (if E has keys else: for (k, v) in E: D[k] = v) then: for k in F: D[k] = F[k]" );
18131813
18141814PyDoc_STRVAR (fromkeys__doc__ ,
18151815"dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v.\n\
@@ -1830,6 +1830,15 @@ PyDoc_STRVAR(itervalues__doc__,
18301830PyDoc_STRVAR (iteritems__doc__ ,
18311831"D.iteritems() -> an iterator over the (key, value) items of D" );
18321832
1833+ /* Forward */
1834+ static PyObject * dictkeys_new (PyObject * );
1835+ static PyObject * dictitems_new (PyObject * );
1836+ static PyObject * dictvalues_new (PyObject * );
1837+
1838+ PyDoc_STRVAR (KEYS__doc__ , "D.KEYS() -> a set-like object for D's keys" );
1839+ PyDoc_STRVAR (ITEMS__doc__ , "D.ITEMS() -> a set-like object for D's items" );
1840+ PyDoc_STRVAR (VALUES__doc__ , "D.VALUES() -> a set-like object for D's values" );
1841+
18331842static PyMethodDef mapp_methods [] = {
18341843 {"__contains__" ,(PyCFunction )dict_contains , METH_O | METH_COEXIST ,
18351844 contains__doc__ },
@@ -1845,6 +1854,12 @@ static PyMethodDef mapp_methods[] = {
18451854 popitem__doc__ },
18461855 {"keys" , (PyCFunction )dict_keys , METH_NOARGS ,
18471856 keys__doc__ },
1857+ {"KEYS" , (PyCFunction )dictkeys_new , METH_NOARGS ,
1858+ KEYS__doc__ },
1859+ {"ITEMS" , (PyCFunction )dictitems_new , METH_NOARGS ,
1860+ ITEMS__doc__ },
1861+ {"VALUES" , (PyCFunction )dictvalues_new , METH_NOARGS ,
1862+ VALUES__doc__ },
18481863 {"items" , (PyCFunction )dict_items , METH_NOARGS ,
18491864 items__doc__ },
18501865 {"values" , (PyCFunction )dict_values , METH_NOARGS ,
@@ -2078,10 +2093,12 @@ dictiter_len(dictiterobject *di)
20782093 return PyInt_FromSize_t (len );
20792094}
20802095
2081- PyDoc_STRVAR (length_hint_doc , "Private method returning an estimate of len(list(it))." );
2096+ PyDoc_STRVAR (length_hint_doc ,
2097+ "Private method returning an estimate of len(list(it))." );
20822098
20832099static PyMethodDef dictiter_methods [] = {
2084- {"__length_hint__" , (PyCFunction )dictiter_len , METH_NOARGS , length_hint_doc },
2100+ {"__length_hint__" , (PyCFunction )dictiter_len , METH_NOARGS ,
2101+ length_hint_doc },
20852102 {NULL , NULL } /* sentinel */
20862103};
20872104
@@ -2317,3 +2334,225 @@ PyTypeObject PyDictIterItem_Type = {
23172334 dictiter_methods , /* tp_methods */
23182335 0 ,
23192336};
2337+
2338+
2339+ /* View objects for keys(), items(), values(). */
2340+ /* While this is incomplete, we use KEYS(), ITEMS(), VALUES(). */
2341+
2342+ /* The instance lay-out is the same for all three; but the type differs. */
2343+
2344+ typedef struct {
2345+ PyObject_HEAD
2346+ dictobject * ds_dict ;
2347+ } dictviewobject ;
2348+
2349+
2350+ static void
2351+ dictview_dealloc (dictviewobject * ds )
2352+ {
2353+ Py_XDECREF (ds -> ds_dict );
2354+ PyObject_Del (ds );
2355+ }
2356+
2357+ static PyObject *
2358+ dictview_length_hint (dictviewobject * ds )
2359+ {
2360+ Py_ssize_t len = 0 ;
2361+ if (ds -> ds_dict != NULL )
2362+ len = ds -> ds_dict -> ma_used ;
2363+ return PyInt_FromSize_t (len );
2364+ }
2365+
2366+ static PyObject *
2367+ dictview_new (PyObject * dict , PyTypeObject * type )
2368+ {
2369+ dictviewobject * ds ;
2370+ if (dict == NULL ) {
2371+ PyErr_BadInternalCall ();
2372+ return NULL ;
2373+ }
2374+ if (!PyDict_Check (dict )) {
2375+ /* XXX Get rid of this restriction later */
2376+ PyErr_Format (PyExc_TypeError ,
2377+ "%s() requires a dict argument, not '%s'" ,
2378+ type -> tp_name , dict -> ob_type -> tp_name );
2379+ return NULL ;
2380+ }
2381+ ds = PyObject_New (dictviewobject , type );
2382+ if (ds == NULL )
2383+ return NULL ;
2384+ Py_INCREF (dict );
2385+ ds -> ds_dict = (dictobject * )dict ;
2386+ return (PyObject * )ds ;
2387+ }
2388+
2389+ /* dict_keys */
2390+
2391+ static PyObject *
2392+ dictkeys_iter (dictviewobject * ds )
2393+ {
2394+ if (ds -> ds_dict == NULL ) {
2395+ Py_RETURN_NONE ;
2396+ }
2397+ return dictiter_new (ds -> ds_dict , & PyDictIterKey_Type );
2398+ }
2399+
2400+ static PyMethodDef dictkeys_methods [] = {
2401+ {"__length_hint__" , (PyCFunction )dictview_length_hint , METH_NOARGS ,
2402+ length_hint_doc },
2403+ {NULL , NULL } /* sentinel */
2404+ };
2405+
2406+ PyTypeObject PyDictKeys_Type = {
2407+ PyObject_HEAD_INIT (& PyType_Type )
2408+ 0 , /* ob_size */
2409+ "dict_keys" , /* tp_name */
2410+ sizeof (dictviewobject ), /* tp_basicsize */
2411+ 0 , /* tp_itemsize */
2412+ /* methods */
2413+ (destructor )dictview_dealloc , /* tp_dealloc */
2414+ 0 , /* tp_print */
2415+ 0 , /* tp_getattr */
2416+ 0 , /* tp_setattr */
2417+ 0 , /* tp_compare */
2418+ 0 , /* tp_repr */
2419+ 0 , /* tp_as_number */
2420+ 0 , /* tp_as_sequence */
2421+ 0 , /* tp_as_mapping */
2422+ 0 , /* tp_hash */
2423+ 0 , /* tp_call */
2424+ 0 , /* tp_str */
2425+ PyObject_GenericGetAttr , /* tp_getattro */
2426+ 0 , /* tp_setattro */
2427+ 0 , /* tp_as_buffer */
2428+ Py_TPFLAGS_DEFAULT , /* tp_flags */
2429+ 0 , /* tp_doc */
2430+ 0 , /* tp_traverse */
2431+ 0 , /* tp_clear */
2432+ 0 , /* tp_richcompare */
2433+ 0 , /* tp_weaklistoffset */
2434+ (getiterfunc )dictkeys_iter , /* tp_iter */
2435+ 0 , /* tp_iternext */
2436+ dictkeys_methods , /* tp_methods */
2437+ 0 ,
2438+ };
2439+
2440+ static PyObject *
2441+ dictkeys_new (PyObject * dict )
2442+ {
2443+ return dictview_new (dict , & PyDictKeys_Type );
2444+ }
2445+
2446+ /* dict_items */
2447+
2448+ static PyObject *
2449+ dictitems_iter (dictviewobject * ds )
2450+ {
2451+ if (ds -> ds_dict == NULL ) {
2452+ Py_RETURN_NONE ;
2453+ }
2454+ return dictiter_new (ds -> ds_dict , & PyDictIterItem_Type );
2455+ }
2456+
2457+ static PyMethodDef dictitems_methods [] = {
2458+ {"__length_hint__" , (PyCFunction )dictview_length_hint , METH_NOARGS ,
2459+ length_hint_doc },
2460+ {NULL , NULL } /* sentinel */
2461+ };
2462+
2463+ PyTypeObject PyDictItems_Type = {
2464+ PyObject_HEAD_INIT (& PyType_Type )
2465+ 0 , /* ob_size */
2466+ "dict_items" , /* tp_name */
2467+ sizeof (dictviewobject ), /* tp_basicsize */
2468+ 0 , /* tp_itemsize */
2469+ /* methods */
2470+ (destructor )dictview_dealloc , /* tp_dealloc */
2471+ 0 , /* tp_print */
2472+ 0 , /* tp_getattr */
2473+ 0 , /* tp_setattr */
2474+ 0 , /* tp_compare */
2475+ 0 , /* tp_repr */
2476+ 0 , /* tp_as_number */
2477+ 0 , /* tp_as_sequence */
2478+ 0 , /* tp_as_mapping */
2479+ 0 , /* tp_hash */
2480+ 0 , /* tp_call */
2481+ 0 , /* tp_str */
2482+ PyObject_GenericGetAttr , /* tp_getattro */
2483+ 0 , /* tp_setattro */
2484+ 0 , /* tp_as_buffer */
2485+ Py_TPFLAGS_DEFAULT , /* tp_flags */
2486+ 0 , /* tp_doc */
2487+ 0 , /* tp_traverse */
2488+ 0 , /* tp_clear */
2489+ 0 , /* tp_richcompare */
2490+ 0 , /* tp_weaklistoffset */
2491+ (getiterfunc )dictitems_iter , /* tp_iter */
2492+ 0 , /* tp_iternext */
2493+ dictitems_methods , /* tp_methods */
2494+ 0 ,
2495+ };
2496+
2497+ static PyObject *
2498+ dictitems_new (PyObject * dict )
2499+ {
2500+ return dictview_new (dict , & PyDictItems_Type );
2501+ }
2502+
2503+ /* dict_values */
2504+
2505+ static PyObject *
2506+ dictvalues_iter (dictviewobject * ds )
2507+ {
2508+ if (ds -> ds_dict == NULL ) {
2509+ Py_RETURN_NONE ;
2510+ }
2511+ return dictiter_new (ds -> ds_dict , & PyDictIterValue_Type );
2512+ }
2513+
2514+ static PyMethodDef dictvalues_methods [] = {
2515+ {"__length_hint__" , (PyCFunction )dictview_length_hint , METH_NOARGS ,
2516+ length_hint_doc },
2517+ {NULL , NULL } /* sentinel */
2518+ };
2519+
2520+ PyTypeObject PyDictValues_Type = {
2521+ PyObject_HEAD_INIT (& PyType_Type )
2522+ 0 , /* ob_size */
2523+ "dict_values" , /* tp_name */
2524+ sizeof (dictviewobject ), /* tp_basicsize */
2525+ 0 , /* tp_itemsize */
2526+ /* methods */
2527+ (destructor )dictview_dealloc , /* tp_dealloc */
2528+ 0 , /* tp_print */
2529+ 0 , /* tp_getattr */
2530+ 0 , /* tp_setattr */
2531+ 0 , /* tp_compare */
2532+ 0 , /* tp_repr */
2533+ 0 , /* tp_as_number */
2534+ 0 , /* tp_as_sequence */
2535+ 0 , /* tp_as_mapping */
2536+ 0 , /* tp_hash */
2537+ 0 , /* tp_call */
2538+ 0 , /* tp_str */
2539+ PyObject_GenericGetAttr , /* tp_getattro */
2540+ 0 , /* tp_setattro */
2541+ 0 , /* tp_as_buffer */
2542+ Py_TPFLAGS_DEFAULT , /* tp_flags */
2543+ 0 , /* tp_doc */
2544+ 0 , /* tp_traverse */
2545+ 0 , /* tp_clear */
2546+ 0 , /* tp_richcompare */
2547+ 0 , /* tp_weaklistoffset */
2548+ (getiterfunc )dictvalues_iter , /* tp_iter */
2549+ 0 , /* tp_iternext */
2550+ dictvalues_methods , /* tp_methods */
2551+ 0 ,
2552+ };
2553+
2554+ static PyObject *
2555+ dictvalues_new (PyObject * dict )
2556+ {
2557+ return dictview_new (dict , & PyDictValues_Type );
2558+ }
0 commit comments