Commit 54628fa7 authored by Raymond Hettinger's avatar Raymond Hettinger

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

parent fe800a34
...@@ -60,6 +60,7 @@ class TestDefaultDict(unittest.TestCase): ...@@ -60,6 +60,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)
...@@ -112,6 +113,12 @@ class TestDefaultDict(unittest.TestCase): ...@@ -112,6 +113,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)
......
...@@ -1170,6 +1170,9 @@ defdict_copy(defdictobject *dd) ...@@ -1170,6 +1170,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);
} }
...@@ -1316,7 +1319,7 @@ defdict_init(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -1316,7 +1319,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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment