SF #904720:  dict.update should take a 2-tuple sequence like dict.__init_
(Championed by Bob Ippolito.)

The update() method for mappings now accepts all the same argument forms
as the dict() constructor.  This includes item lists and/or keyword
arguments.
diff --git a/Doc/lib/libstdtypes.tex b/Doc/lib/libstdtypes.tex
index 7c5cba0..c39be28 100644
--- a/Doc/lib/libstdtypes.tex
+++ b/Doc/lib/libstdtypes.tex
@@ -1266,9 +1266,9 @@
           {a copy of \var{a}'s list of (\var{key}, \var{value}) pairs}
           {(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}.update(\optional{\var{b}})}
+          {updates (and overwrites) key/value pairs from \var{b}}
+          {(9)}
   \lineiii{\var{a}.fromkeys(\var{seq}\optional{, \var{value}})}
           {Creates a new dictionary with keys from \var{seq} and values set to \var{value}}
           {(7)}			   
@@ -1338,6 +1338,13 @@
 value is given and the key is not found.  \versionadded{2.3}
 \end{description}
 
+\item[(9)] \function{update()} accepts either another mapping object
+or an iterable of key/value pairs (as a tuple or other iterable of
+length two).  If keyword arguments are specified, the mapping is
+then is updated with those key/value pairs:
+\samp{d.update(red=1, blue=2)}.
+\versionchanged[Allowed the argument to be an iterable of key/value
+                pairs and allowed keyword arguments]{2.4}
 
 \subsection{File Objects
             \label{bltin-file-objects}}
diff --git a/Doc/whatsnew/whatsnew24.tex b/Doc/whatsnew/whatsnew24.tex
index eb377be..24650fa 100644
--- a/Doc/whatsnew/whatsnew24.tex
+++ b/Doc/whatsnew/whatsnew24.tex
@@ -134,6 +134,10 @@
 
 \begin{itemize}
 
+\item The \method{dict.update()} method now accepts the same
+argument forms as the \class{dict} constructor.  This includes any
+mapping, any iterable of key/value pairs, and/or keyword arguments.       
+
 \item The string methods, \method{ljust()}, \method{rjust()}, and
 \method{center()} now take an optional argument for specifying a
 fill character other than a space.
diff --git a/Lib/UserDict.py b/Lib/UserDict.py
index 8141e7f..87cc6a3 100644
--- a/Lib/UserDict.py
+++ b/Lib/UserDict.py
@@ -4,8 +4,6 @@
     def __init__(self, dict=None, **kwargs):
         self.data = {}
         if dict is not None:
-            if not hasattr(dict,'keys'):
-                dict = type({})(dict)   # make mapping from a sequence
             self.update(dict)
         if len(kwargs):
             self.update(kwargs)
@@ -39,14 +37,18 @@
     def itervalues(self): return self.data.itervalues()
     def values(self): return self.data.values()
     def has_key(self, key): return self.data.has_key(key)
-    def update(self, dict):
-        if isinstance(dict, UserDict):
+    def update(self, dict=None, **kwargs):
+        if dict is None:
+            pass
+        elif isinstance(dict, UserDict):
             self.data.update(dict.data)
-        elif isinstance(dict, type(self.data)):
+        elif isinstance(dict, type({})) or not hasattr(dict, 'items'):
             self.data.update(dict)
         else:
             for k, v in dict.items():
                 self[k] = v
+        if len(kwargs):
+            self.data.update(kwargs)
     def get(self, key, failobj=None):
         if not self.has_key(key):
             return failobj
@@ -136,17 +138,21 @@
             raise KeyError, 'container is empty'
         del self[k]
         return (k, v)
-    def update(self, other):
+    def update(self, other=None, **kwargs):
         # Make progressively weaker assumptions about "other"
-        if hasattr(other, 'iteritems'):  # iteritems saves memory and lookups
+        if other is None:
+            pass
+        elif hasattr(other, 'iteritems'):  # iteritems saves memory and lookups
             for k, v in other.iteritems():
                 self[k] = v
-        elif hasattr(other, '__iter__'): # iter saves memory
-            for k in other:
-                self[k] = other[k]
-        else:
+        elif hasattr(other, 'keys'):
             for k in other.keys():
                 self[k] = other[k]
+        else:
+            for k, v in other:
+                self[k] = v
+        if kwargs:
+            self.update(kwargs)
     def get(self, key, default=None):
         try:
             return self[key]
diff --git a/Lib/os.py b/Lib/os.py
index 8cec912..fdb9a46 100644
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -433,9 +433,6 @@
                 return key.upper() in self.data
             def get(self, key, failobj=None):
                 return self.data.get(key.upper(), failobj)
-            def update(self, dict):
-                for k, v in dict.items():
-                    self[k] = v
             def copy(self):
                 return dict(self)
 
@@ -447,9 +444,6 @@
             def __setitem__(self, key, item):
                 putenv(key, item)
                 self.data[key] = item
-            def update(self, dict):
-                for k, v in dict.items():
-                    self[k] = v
             try:
                 unsetenv
             except NameError:
diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py
index 99554c7..f3c7c8c 100644
--- a/Lib/test/test_call.py
+++ b/Lib/test/test_call.py
@@ -86,41 +86,41 @@
         self.assertRaises(TypeError, {}.keys, x=2, y=2)
 
     def test_oldargs1_0(self):
-        self.assertRaises(TypeError, {}.update)
+        self.assertRaises(TypeError, [].count)
 
     def test_oldargs1_1(self):
-        {}.update({})
+        [].count(1)
 
     def test_oldargs1_2(self):
-        self.assertRaises(TypeError, {}.update, {}, 1)
+        self.assertRaises(TypeError, [].count, 1, 2)
 
     def test_oldargs1_0_ext(self):
         try:
-            {}.update(*())
+            [].count(*())
         except TypeError:
             pass
         else:
             raise RuntimeError
 
     def test_oldargs1_1_ext(self):
-        {}.update(*({},))
+        [].count(*(1,))
 
     def test_oldargs1_2_ext(self):
         try:
-            {}.update(*({}, 2))
+            [].count(*(1, 2))
         except TypeError:
             pass
         else:
             raise RuntimeError
 
     def test_oldargs1_0_kw(self):
-        self.assertRaises(TypeError, {}.update, x=2)
+        self.assertRaises(TypeError, [].count, x=2)
 
     def test_oldargs1_1_kw(self):
-        self.assertRaises(TypeError, {}.update, {}, x=2)
+        self.assertRaises(TypeError, [].count, {}, x=2)
 
     def test_oldargs1_2_kw(self):
-        self.assertRaises(TypeError, {}.update, x=2, y=2)
+        self.assertRaises(TypeError, [].count, x=2, y=2)
 
 
 def test_main():
diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index aa8f854..4b4e19c 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -253,7 +253,7 @@
 if d != {1:1, 2:2, 3:3}: raise TestFailed, 'dict update'
 d.clear()
 try: d.update(None)
-except AttributeError: pass
+except (TypeError, AttributeError): pass
 else: raise TestFailed, 'dict.update(None), AttributeError expected'
 class SimpleUserDict:
     def __init__(self):
diff --git a/Lib/test/test_userdict.py b/Lib/test/test_userdict.py
index 602fd90..0ed4369 100644
--- a/Lib/test/test_userdict.py
+++ b/Lib/test/test_userdict.py
@@ -93,8 +93,12 @@
         #update
         p.update(self.reference)
         self.assertEqual(dict(p), self.reference)
+        items = p.items()
+        p = self._empty_mapping()
+        p.update(items)
+        self.assertEqual(dict(p), self.reference)
         d = self._full_mapping(self.reference)
-        #setdefaullt
+        #setdefault
         key, value = d.iteritems().next()
         knownkey, knownvalue = self.other.iteritems().next()
         self.assertEqual(d.setdefault(key, knownvalue), value)
diff --git a/Lib/weakref.py b/Lib/weakref.py
index 09bed65..5c66186 100644
--- a/Lib/weakref.py
+++ b/Lib/weakref.py
@@ -122,10 +122,15 @@
         else:
             return wr()
 
-    def update(self, dict):
+    def update(self, dict=None, **kwargs):
         d = self.data
-        for key, o in dict.items():
-            d[key] = ref(o, self.__makeremove(key))
+        if dict is not None:
+            if not hasattr(dict, "items"):
+                dict = type({})(dict)
+            for key, o in dict.items():
+                d[key] = ref(o, self.__makeremove(key))
+        if len(kwargs):
+            self.update(kwargs)
 
     def values(self):
         L = []
@@ -239,10 +244,15 @@
     def setdefault(self, key, default):
         return self.data.setdefault(ref(key, self._remove),default)
 
-    def update(self, dict):
+    def update(self, dict=None, **kwargs):
         d = self.data
-        for key, value in dict.items():
-            d[ref(key, self._remove)] = value
+        if dict is not None:
+            if not hasattr(dict, "items"):
+                dict = type({})(dict)
+            for key, value in dict.items():
+                d[ref(key, self._remove)] = value
+        if len(kwargs):
+            self.update(kwargs)
 
 
 class BaseIter:
diff --git a/Misc/ACKS b/Misc/ACKS
index 61b07cb..befc46b 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -273,6 +273,7 @@
 Juan David Ibáñez Palomar
 Tony Ingraldi
 John Interrante
+Bob Ippolito
 Ben Jackson
 Paul Jackson
 David Jacobs
diff --git a/Misc/NEWS b/Misc/NEWS
index 1bd6c2b..72232c8 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -32,6 +32,10 @@
   the overallocation is no more than three elements -- this improves space
   utilization for applications that have large numbers of small lists.
 
+- The dict.update() method now accepts all the same argument forms
+  as the dict() constructor.  This now includes item lists and/or
+  keyword arguments.
+
 - Support for arbitrary objects supporting the read-only buffer
   interface as the co_code field of code objects (something that was
   only possible to create from C code) has been removed.
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index eb0222c..b5cbd66 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1029,10 +1029,30 @@
 	return NULL;
 }
 
-static PyObject *
-dict_update(PyObject *mp, PyObject *other)
+static int
+dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, char *methname)
 {
-	if (PyDict_Update(mp, other) < 0)
+	PyObject *arg = NULL;
+	int result = 0;
+
+	if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg))
+		result = -1;
+
+	else if (arg != NULL) {
+		if (PyObject_HasAttrString(arg, "keys"))
+			result = PyDict_Merge(self, arg, 1);
+		else
+			result = PyDict_MergeFromSeq2(self, arg, 1);
+	}
+	if (result == 0 && kwds != NULL)
+		result = PyDict_Merge(self, kwds, 1);
+	return result;
+}
+
+static PyObject *
+dict_update(PyObject *self, PyObject *args, PyObject *kwds)
+{
+	if (dict_update_common(self, args, kwds, "update") == -1)
 		return NULL;
 	Py_INCREF(Py_None);
 	return Py_None;
@@ -1806,7 +1826,7 @@
 	 items__doc__},
 	{"values",	(PyCFunction)dict_values,	METH_NOARGS,
 	 values__doc__},
-	{"update",	(PyCFunction)dict_update,	METH_O,
+	{"update",	(PyCFunction)dict_update,	METH_VARARGS | METH_KEYWORDS,
 	 update__doc__},
 	{"fromkeys",	(PyCFunction)dict_fromkeys,	METH_VARARGS | METH_CLASS,
 	 fromkeys__doc__},
@@ -1875,21 +1895,7 @@
 static int
 dict_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
-	PyObject *arg = NULL;
-	int result = 0;
-
-	if (!PyArg_UnpackTuple(args, "dict", 0, 1, &arg))
-		result = -1;
-
-	else if (arg != NULL) {
-		if (PyObject_HasAttrString(arg, "keys"))
-			result = PyDict_Merge(self, arg, 1);
-		else
-			result = PyDict_MergeFromSeq2(self, arg, 1);
-	}
-	if (result == 0 && kwds != NULL)
-		result = PyDict_Merge(self, kwds, 1);
-	return result;
+	return dict_update_common(self, args, kwds, "dict");
 }
 
 static long