mirror of https://github.com/python/cpython
gh-109174: Add support of SimpleNamespace in copy.replace() (GH-109175)
This commit is contained in:
parent
0eab2427b1
commit
92578919a6
|
@ -504,6 +504,8 @@ Additional Utility Classes and Functions
|
|||
However, for a structured record type use :func:`~collections.namedtuple`
|
||||
instead.
|
||||
|
||||
:class:`!SimpleNamespace` objects are supported by :func:`copy.replace`.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
|
|
|
@ -1900,6 +1900,33 @@ class SimpleNamespaceTests(unittest.TestCase):
|
|||
|
||||
self.assertEqual(ns, ns_roundtrip, pname)
|
||||
|
||||
def test_replace(self):
|
||||
ns = types.SimpleNamespace(x=11, y=22)
|
||||
|
||||
ns2 = copy.replace(ns)
|
||||
self.assertEqual(ns2, ns)
|
||||
self.assertIsNot(ns2, ns)
|
||||
self.assertIs(type(ns2), types.SimpleNamespace)
|
||||
self.assertEqual(vars(ns2), {'x': 11, 'y': 22})
|
||||
ns2.x = 3
|
||||
self.assertEqual(ns.x, 11)
|
||||
ns.x = 4
|
||||
self.assertEqual(ns2.x, 3)
|
||||
|
||||
self.assertEqual(vars(copy.replace(ns, x=1)), {'x': 1, 'y': 22})
|
||||
self.assertEqual(vars(copy.replace(ns, y=2)), {'x': 4, 'y': 2})
|
||||
self.assertEqual(vars(copy.replace(ns, x=1, y=2)), {'x': 1, 'y': 2})
|
||||
|
||||
def test_replace_subclass(self):
|
||||
class Spam(types.SimpleNamespace):
|
||||
pass
|
||||
|
||||
spam = Spam(ham=8, eggs=9)
|
||||
spam2 = copy.replace(spam, ham=5)
|
||||
|
||||
self.assertIs(type(spam2), Spam)
|
||||
self.assertEqual(vars(spam2), {'ham': 5, 'eggs': 9})
|
||||
|
||||
def test_fake_namespace_compare(self):
|
||||
# Issue #24257: Incorrect use of PyObject_IsInstance() caused
|
||||
# SystemError.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Add support of :class:`types.SimpleNamespace` in :func:`copy.replace`.
|
|
@ -189,9 +189,37 @@ namespace_reduce(_PyNamespaceObject *ns, PyObject *Py_UNUSED(ignored))
|
|||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
namespace_replace(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
if (!_PyArg_NoPositional("__replace__", args)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *result = PyObject_CallNoArgs((PyObject *)Py_TYPE(self));
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyDict_Update(((_PyNamespaceObject*)result)->ns_dict,
|
||||
((_PyNamespaceObject*)self)->ns_dict) < 0)
|
||||
{
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
if (kwargs) {
|
||||
if (PyDict_Update(((_PyNamespaceObject*)result)->ns_dict, kwargs) < 0) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef namespace_methods[] = {
|
||||
{"__reduce__", (PyCFunction)namespace_reduce, METH_NOARGS,
|
||||
namespace_reduce__doc__},
|
||||
{"__replace__", _PyCFunction_CAST(namespace_replace), METH_VARARGS|METH_KEYWORDS, NULL},
|
||||
{NULL, NULL} // sentinel
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue