@@ -1047,26 +1047,79 @@ dict_update(register dictobject *mp, PyObject *args)
10471047 register int i ;
10481048 dictobject * other ;
10491049 dictentry * entry ;
1050- if (!PyArg_Parse (args , "O!" , & PyDict_Type , & other ))
1050+ PyObject * param ;
1051+ /* We accept for the argument either a concrete dictionary object,
1052+ * or an abstract "mapping" object. For the former, we can do
1053+ * things quite efficiently. For the latter, we only require that
1054+ * PyMapping_Keys() and PyObject_GetItem() be supported.
1055+ */
1056+ if (!PyArg_ParseTuple (args , "O:update" , & param ))
10511057 return NULL ;
1052- if (other == mp || other -> ma_used == 0 )
1053- goto done ; /* a.update(a) or a.update({}); nothing to do */
1054- /* Do one big resize at the start, rather than incrementally
1055- resizing as we insert new items. Expect that there will be
1056- no (or few) overlapping keys. */
1057- if ((mp -> ma_fill + other -> ma_used )* 3 >= (mp -> ma_mask + 1 )* 2 ) {
1058- if (dictresize (mp , (mp -> ma_used + other -> ma_used )* 3 /2 ) != 0 )
1059- return NULL ;
1058+
1059+ if (PyDict_Check (param )) {
1060+ other = (dictobject * )param ;
1061+ if (other == mp || other -> ma_used == 0 )
1062+ /* a.update(a) or a.update({}); nothing to do */
1063+ goto done ;
1064+ /* Do one big resize at the start, rather than
1065+ * incrementally resizing as we insert new items. Expect
1066+ * that there will be no (or few) overlapping keys.
1067+ */
1068+ if ((mp -> ma_fill + other -> ma_used )* 3 >= (mp -> ma_mask + 1 )* 2 ) {
1069+ if (dictresize (mp , (mp -> ma_used + other -> ma_used )* 3 /2 ) != 0 )
1070+ return NULL ;
1071+ }
1072+ for (i = 0 ; i <= other -> ma_mask ; i ++ ) {
1073+ entry = & other -> ma_table [i ];
1074+ if (entry -> me_value != NULL ) {
1075+ Py_INCREF (entry -> me_key );
1076+ Py_INCREF (entry -> me_value );
1077+ insertdict (mp , entry -> me_key , entry -> me_hash ,
1078+ entry -> me_value );
1079+ }
1080+ }
10601081 }
1061- for (i = 0 ; i <= other -> ma_mask ; i ++ ) {
1062- entry = & other -> ma_table [i ];
1063- if (entry -> me_value != NULL ) {
1064- Py_INCREF (entry -> me_key );
1065- Py_INCREF (entry -> me_value );
1066- insertdict (mp , entry -> me_key , entry -> me_hash ,
1067- entry -> me_value );
1082+ else {
1083+ /* Do it the generic, slower way */
1084+ PyObject * keys = PyMapping_Keys (param );
1085+ PyObject * iter ;
1086+ PyObject * key , * value ;
1087+ int status ;
1088+
1089+ if (keys == NULL )
1090+ /* Docstring says this is equivalent to E.keys() so
1091+ * if E doesn't have a .keys() method we want
1092+ * AttributeError to percolate up. Might as well
1093+ * do the same for any other error.
1094+ */
1095+ return NULL ;
1096+
1097+ iter = PyObject_GetIter (keys );
1098+ Py_DECREF (keys );
1099+ if (iter == NULL )
1100+ return NULL ;
1101+
1102+ for (key = PyIter_Next (iter ); key ; key = PyIter_Next (iter )) {
1103+ value = PyObject_GetItem (param , key );
1104+ if (value == NULL ) {
1105+ Py_DECREF (iter );
1106+ Py_DECREF (key );
1107+ return NULL ;
1108+ }
1109+ status = PyDict_SetItem ((PyObject * )mp , key , value );
1110+ Py_DECREF (key );
1111+ Py_DECREF (value );
1112+ if (status < 0 ) {
1113+ Py_DECREF (iter );
1114+ return NULL ;
1115+ }
10681116 }
1117+ Py_DECREF (iter );
1118+ if (PyErr_Occurred ())
1119+ /* Iterator completed, via error */
1120+ return NULL ;
10691121 }
1122+
10701123 done :
10711124 Py_INCREF (Py_None );
10721125 return Py_None ;
@@ -1626,7 +1679,7 @@ static PyMethodDef mapp_methods[] = {
16261679 items__doc__ },
16271680 {"values" , (PyCFunction )dict_values , METH_OLDARGS ,
16281681 values__doc__ },
1629- {"update" , (PyCFunction )dict_update , METH_OLDARGS ,
1682+ {"update" , (PyCFunction )dict_update , METH_VARARGS ,
16301683 update__doc__ },
16311684 {"clear" , (PyCFunction )dict_clear , METH_OLDARGS ,
16321685 clear__doc__ },
0 commit comments