Issue 6637: defaultdict.copy() failed with an empty factory.

This commit is contained in:
Raymond Hettinger 2009-08-04 18:49:26 +00:00
parent 6416f810e8
commit d6119ef883
3 changed files with 15 additions and 1 deletions

View File

@ -59,6 +59,7 @@ class TestDefaultDict(unittest.TestCase):
d1 = defaultdict() d1 = defaultdict()
self.assertEqual(d1.default_factory, None) self.assertEqual(d1.default_factory, None)
self.assertEqual(repr(d1), "defaultdict(None, {})") self.assertEqual(repr(d1), "defaultdict(None, {})")
self.assertEqual(eval(repr(d1)), d1)
d1[11] = 41 d1[11] = 41
self.assertEqual(repr(d1), "defaultdict(None, {11: 41})") self.assertEqual(repr(d1), "defaultdict(None, {11: 41})")
d2 = defaultdict(int) d2 = defaultdict(int)
@ -111,6 +112,12 @@ class TestDefaultDict(unittest.TestCase):
d4[12] d4[12]
self.assertEqual(d4, {42: [], 12: []}) self.assertEqual(d4, {42: [], 12: []})
# Issue 6637: Copy fails for empty default dict
d = defaultdict()
d['a'] = 42
e = d.copy()
self.assertEqual(e['a'], 42)
def test_shallow_copy(self): def test_shallow_copy(self):
d1 = defaultdict(foobar, {1: 1}) d1 = defaultdict(foobar, {1: 1})
d2 = copy.copy(d1) d2 = copy.copy(d1)

View File

@ -70,6 +70,10 @@ Core and Builtins
Library Library
------- -------
- Issue #6637: defaultdict.copy() did not work when the default factory
was left unspecified. Also, the eval/repr round-trip would fail when
the default_factory was None.
- Issue #1424152: Fix for httplib, urllib2 to support SSL while working through - Issue #1424152: Fix for httplib, urllib2 to support SSL while working through
proxy. Original patch by Christopher Li, changes made by Senthil Kumaran. proxy. Original patch by Christopher Li, changes made by Senthil Kumaran.

View File

@ -1191,6 +1191,9 @@ defdict_copy(defdictobject *dd)
whose class constructor has the same signature. Subclasses that whose class constructor has the same signature. Subclasses that
define a different constructor signature must override copy(). define a different constructor signature must override copy().
*/ */
if (dd->default_factory == NULL)
return PyObject_CallFunctionObjArgs((PyObject*)Py_TYPE(dd), Py_None, dd, NULL);
return PyObject_CallFunctionObjArgs((PyObject*)Py_TYPE(dd), return PyObject_CallFunctionObjArgs((PyObject*)Py_TYPE(dd),
dd->default_factory, dd, NULL); dd->default_factory, dd, NULL);
} }
@ -1354,7 +1357,7 @@ defdict_init(PyObject *self, PyObject *args, PyObject *kwds)
Py_ssize_t n = PyTuple_GET_SIZE(args); Py_ssize_t n = PyTuple_GET_SIZE(args);
if (n > 0) { if (n > 0) {
newdefault = PyTuple_GET_ITEM(args, 0); newdefault = PyTuple_GET_ITEM(args, 0);
if (!PyCallable_Check(newdefault)) { if (!PyCallable_Check(newdefault) && newdefault != Py_None) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"first argument must be callable"); "first argument must be callable");
return -1; return -1;