8000 gh-109174: Add support of SimpleNamespace in copy.replace() (GH-109175) · python/cpython@9257891 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9257891

Browse files
gh-109174: Add support of SimpleNamespace in copy.replace() (GH-109175)
1 parent 0eab242 commit 9257891

File tree

4 files changed

+58
-0
lines changed

4 files changed

+58
-0
lines changed

Doc/library/types.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,8 @@ Additional Utility Classes and Functions
504504
However, for a structured record type use :func:`~collections.namedtuple`
505505
instead.
506506

507+
:class:`!SimpleNamespace` objects are supported by :func:`copy.replace`.
508+
507509
.. versionadded:: 3.3
508510

509511
.. versionchanged:: 3.9

Lib/test/test_types.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,33 @@ def test_pickle(self):
19001900

19011901
self.assertEqual(ns, ns_roundtrip, pname)
19021902

1903+
def test_replace(self):
1904+
ns = types.SimpleNamespace(x=11, y=22)
1905+
1906+
ns2 = copy.replace(ns)
1907+
self.assertEqual(ns2, ns)
1908+
self.assertIsNot(ns2, ns)
1909+
self.assertIs(type(ns2), types.SimpleNamespace)
1910+
self.assertEqual(vars(ns2), {'x': 11, 'y': 22})
1911+
ns2.x = 3
1912+
self.assertEqual(ns.x, 11)
1913+
ns.x = 4
1914+
self.assertEqual(ns2.x, 3)
1915+
1916+
self.assertEqual(vars(copy.replace(ns, x=1)), {'x': 1, 'y': 22})
1917+
self.assertEqual(vars(copy.replace(ns, y=2)), {'x': 4, 'y': 2})
1918+
self.assertEqual(vars(copy.replace(ns, x=1, y=2)), {'x': 1, 'y': 2})
1919+
1920+
def test_replace_subclass(self):
1921+
class Spam(types.SimpleNamespace):
1922+
pass
1923+
1924+
spam = Spam(ham=8, eggs=9)
1925+
spam2 = copy.replace(spam, ham=5)
1926+
1927+
self.assertIs(type(spam2), Spam)
1928+
self.assertEqual(vars(spam2), {'ham': 5, 'eggs': 9})
1929+
19031930
def test_fake_namespace_compare(self):
19041931
# Issue #24257: Incorrect use of PyObject_IsInstance() caused
19051932
# SystemError.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add support of :class:`types.SimpleNamespace` in :func:`copy.replace`.

Objects/namespaceobject.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,37 @@ namespace_reduce(_PyNamespaceObject *ns, PyObject *Py_UNUSED(ignored))
189189
}
190190

191191

192+
static PyObject *
193+
namespace_replace(PyObject *self, PyObject *args, PyObject *kwargs)
194+
{
195+
if (!_PyArg_NoPositional("__replace__", args)) {
196+
return NULL;
197+
}
198+
199+
PyObject *result = PyObject_CallNoArgs((PyObject *)Py_TYPE(self));
200+
if (!result) {
201+
return NULL;
202+
}
203+
if (PyDict_Update(((_PyNamespaceObject*)result)->ns_dict,
204+
((_PyNamespaceObject*)self)->ns_dict) < 0)
205+
{
206+
Py_DECREF(result);
207+
return NULL;
208+
}
209+
if (kwargs) {
210+
if (PyDict_Update(((_PyNamespaceObject*)result)->ns_dict, kwargs) < 0) {
211+
Py_DECREF(result);
212+
return NULL;
213+
}
214+
}
215+
return result;
216+
}
217+
218+
192219
static PyMethodDef namespace_methods[] = {
193220
{"__reduce__", (PyCFunction)namespace_reduce, METH_NOARGS,
194221
namespace_reduce__doc__},
222+
{"__replace__", _PyCFunction_CAST(namespace_replace), METH_VARARGS|METH_KEYWORDS, NULL},
195223
{NULL, NULL} // sentinel
196224
};
197225

0 commit comments

Comments
 (0)
0