summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_types.py13
-rw-r--r--Objects/namespaceobject.c25
2 files changed, 33 insertions, 5 deletions
diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index de0aac26be..ec10752e6a 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -1159,10 +1159,15 @@ class SimpleNamespaceTests(unittest.TestCase):
def test_pickle(self):
ns = types.SimpleNamespace(breakfast="spam", lunch="spam")
- ns_pickled = pickle.dumps(ns)
- ns_roundtrip = pickle.loads(ns_pickled)
-
- self.assertEqual(ns, ns_roundtrip)
+ for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
+ pname = "protocol {}".format(protocol)
+ try:
+ ns_pickled = pickle.dumps(ns, protocol)
+ except TypeError as e:
+ raise TypeError(pname) from e
+ ns_roundtrip = pickle.loads(ns_pickled)
+
+ self.assertEqual(ns, ns_roundtrip, pname)
def test_main():
diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c
index f9a6f6549d..7e9107a744 100644
--- a/Objects/namespaceobject.c
+++ b/Objects/namespaceobject.c
@@ -173,6 +173,29 @@ namespace_richcompare(PyObject *self, PyObject *other, int op)
}
+PyDoc_STRVAR(namespace_reduce__doc__, "Return state information for pickling");
+
+static PyObject *
+namespace_reduce(register _PyNamespaceObject *ns)
+{
+ PyObject *result, *args = PyTuple_New(0);
+
+ if (!args)
+ return NULL;
+
+ result = PyTuple_Pack(3, (PyObject *)Py_TYPE(ns), args, ns->ns_dict);
+ Py_DECREF(args);
+ return result;
+}
+
+
+static PyMethodDef namespace_methods[] = {
+ {"__reduce__", (PyCFunction)namespace_reduce, METH_NOARGS,
+ namespace_reduce__doc__},
+ {NULL, NULL} /* sentinel */
+};
+
+
PyDoc_STRVAR(namespace_doc,
"A simple attribute-based namespace.\n\
\n\
@@ -207,7 +230,7 @@ PyTypeObject _PyNamespace_Type = {
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
- 0, /* tp_methods */
+ namespace_methods, /* tp_methods */
namespace_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */