Index: Misc/NEWS =================================================================== RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v retrieving revision 1.541 diff -c -r1.541 NEWS *** Misc/NEWS 23 Nov 2002 22:08:15 -0000 1.541 --- Misc/NEWS 25 Nov 2002 10:24:49 -0000 *************** *** 268,273 **** --- 268,278 ---- an optional argument that specifies the characters to strip. For example, "Foo!!!?!?!?".rstrip("?!") -> "Foo". + - Added a new dict method sequpdate(iterable, value=True). This updates + the dictionary with keys from a sequence and a single constant value. + Used for building membership tests and for removing duplicates from a + sequence or iterable. + - Added a new dict method pop(key). This removes and returns the value corresponding to key. [SF patch #539949] Index: Objects/dictobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v retrieving revision 2.131 diff -c -r2.131 dictobject.c *** Objects/dictobject.c 23 Nov 2002 09:45:04 -0000 2.131 --- Objects/dictobject.c 25 Nov 2002 10:24:50 -0000 *************** *** 963,968 **** --- 963,1012 ---- } static PyObject * + dict_sequpdate(PyObject *d, PyObject *args) + { + PyObject *seq; + PyObject *value = Py_True; + PyObject *it; /* iter(seq) */ + PyObject *key; + int i; /* index into seq of current element */ + int status; + + assert(d != NULL); + assert(PyDict_Check(d)); + + if (!PyArg_ParseTuple(args, "O|O:sequpdate", &seq, &value)) + return NULL; + + it = PyObject_GetIter(seq); + if (it == NULL) + return NULL; + + for (i = 0; ; ++i) { + key = PyIter_Next(it); + if (key == NULL) { + if (PyErr_Occurred()) + goto Fail; + break; + } + + /* Update/merge with this (key, value) pair. */ + status = PyDict_SetItem(d, key, value); + Py_XDECREF(key); + if (status < 0) + goto Fail; + } + + Py_DECREF(it); + Py_XINCREF(d); + return d; + + Fail: + Py_DECREF(it); + return NULL; + } + + static PyObject * dict_update(PyObject *mp, PyObject *other) { if (PyDict_Update(mp, other) < 0) *************** *** 1682,1687 **** --- 1726,1735 ---- PyDoc_STRVAR(update__doc__, "D.update(E) -> None. Update D from E: for k in E.keys(): D[k] = E[k]"); + PyDoc_STRVAR(sequpdate__doc__, + "D.sequpdate(S[,v]) -> updated D. Update D from S: for k in S: D[k] = v\n\ + v defaults to True. Returns an updated version of D."); + PyDoc_STRVAR(clear__doc__, "D.clear() -> None. Remove all items from D."); *************** *** 1716,1721 **** --- 1764,1771 ---- values__doc__}, {"update", (PyCFunction)dict_update, METH_O, update__doc__}, + {"sequpdate", (PyCFunction)dict_sequpdate, METH_VARARGS, + sequpdate__doc__}, {"clear", (PyCFunction)dict_clear, METH_NOARGS, clear__doc__}, {"copy", (PyCFunction)dict_copy, METH_NOARGS, Index: Doc/lib/libstdtypes.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libstdtypes.tex,v retrieving revision 1.110 diff -c -r1.110 libstdtypes.tex *** Doc/lib/libstdtypes.tex 16 Nov 2002 00:44:00 -0000 1.110 --- Doc/lib/libstdtypes.tex 25 Nov 2002 10:24:51 -0000 *************** *** 1055,1062 **** {(3)} \lineiii{\var{a}.keys()}{a copy of \var{a}'s list of keys}{(3)} \lineiii{\var{a}.update(\var{b})} ! {\code{for k in \var{b}.keys(): \var{a}[k] = \var{b}[k]}} {} \lineiii{\var{a}.values()}{a copy of \var{a}'s list of values}{(3)} \lineiii{\var{a}.get(\var{k}\optional{, \var{x}})} {\code{\var{a}[\var{k}]} if \code{\var{k} in \var{a}}, --- 1055,1065 ---- {(3)} \lineiii{\var{a}.keys()}{a copy of \var{a}'s list of keys}{(3)} \lineiii{\var{a}.update(\var{b})} ! {\code{for \var{k} in \var{b}.keys(): \var{a}[\var{k}] = \var{b}[\var{k}]}} {} + \lineiii{\var{a}.sequpdate(\var{seq}\optional{, \var{value}})} + {\code{for \var{k} in \var{seq}: \var{a}[\var{k}] = \var{value}}} + {(7)} \lineiii{\var{a}.values()}{a copy of \var{a}'s list of values}{(3)} \lineiii{\var{a}.get(\var{k}\optional{, \var{x}})} {\code{\var{a}[\var{k}]} if \code{\var{k} in \var{a}}, *************** *** 1114,1119 **** --- 1117,1126 ---- \item[(6)] \function{popitem()} is useful to destructively iterate over a dictionary, as often used in set algorithms. + \end{description} + + \item[(7)] \function{sequpdate()} returns the updated dictionary. + \var{value} defaults to \code{True}. \versionadded{2.3} \end{description} Index: Lib/test/test_types.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_types.py,v retrieving revision 1.40 diff -c -r1.40 test_types.py *** Lib/test/test_types.py 19 Nov 2002 20:49:13 -0000 1.40 --- Lib/test/test_types.py 25 Nov 2002 10:24:51 -0000 *************** *** 530,535 **** --- 530,553 ---- try: d.update(FailingUserDict()) except ValueError: pass else: raise TestFailed, 'dict.update(), __getitem__ expected ValueError' + # dict.sequpdate() + d = {1:1, 2:2} + if d.sequpdate('abc') != {1:1, 2:2, 'a':True, 'b':True, 'c':True}: + raise TestFailed, 'dict.sequpdate failed with default value' + if d.sequpdate((4,5),0) != {1:1, 2:2, 'a':True, 'b':True, 'c':True, 4:0, 5:0}: + raise TestFailed, 'dict.sequpdate failed with specified value' + e = d.copy() + if d.sequpdate([]) != e: + raise TestFailed, 'dict.sequpdate failed with null sequence' + if d.sequpdate((1,'b',5),0) != {1:0, 2:2, 'a':True, 'b':0, 'c':True, 4:0, 5:0}: + raise TestFailed, 'dict.sequpdate failed to overwrite existing values' + def g(): + yield 1 + if d.sequpdate(g()) != {1:True, 2:2, 'a':True, 'b':0, 'c':True, 4:0, 5:0}: + raise TestFailed, 'dict.sequpdate failed with a generator' + try: d.sequpdate(3) + except TypeError: pass + else: raise TestFailed, 'dict.sequpdate failed to raise TypeError' # dict.copy() d = {1:1, 2:2, 3:3} if d.copy() != {1:1, 2:2, 3:3}: raise TestFailed, 'dict copy'