Skip to content

Commit d016763

Browse files
author
Tomas Correia
committed
Add update(**kwargs) method to types.SimpleNamespace
1 parent a87f3e0 commit d016763

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

Lib/test/test_types.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import unittest.mock
2222
import weakref
2323
import typing
24+
from types import SimpleNamespace
25+
2426

2527
c_types = import_fresh_module('types', fresh=['_types'])
2628
py_types = import_fresh_module('types', blocked=['_types'])
@@ -2128,6 +2130,23 @@ class FakeSimpleNamespace(str):
21282130
types.SimpleNamespace() > FakeSimpleNamespace()
21292131
with self.assertRaises(TypeError):
21302132
types.SimpleNamespace() >= FakeSimpleNamespace()
2133+
2134+
def test_update_method(self):
2135+
ns = SimpleNamespace(a=1)
2136+
self.assertEqual(ns.a, 1)
2137+
2138+
ns.update(b=2, c=3)
2139+
self.assertEqual(ns.b, 2)
2140+
self.assertEqual(ns.c, 3)
2141+
2142+
# Overwriting existing key
2143+
ns.update(a=42)
2144+
self.assertEqual(ns.a, 42)
2145+
2146+
# No update with no kwargs
2147+
ns.update()
2148+
self.assertEqual(vars(ns), {'a': 42, 'b': 2, 'c': 3})
2149+
21312150

21322151

21332152
class CoroutineTests(unittest.TestCase):

Objects/namespaceobject.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,14 +245,19 @@ namespace_replace(PyObject *self, PyObject *args, PyObject *kwargs)
245245
return result;
246246
}
247247

248+
static PyObject *namespace_update(PyObject *self, PyObject *args, PyObject *kwds);
248249

249250
static PyMethodDef namespace_methods[] = {
250251
{"__reduce__", namespace_reduce, METH_NOARGS,
251252
namespace_reduce__doc__},
252253
{"__replace__", _PyCFunction_CAST(namespace_replace), METH_VARARGS|METH_KEYWORDS,
253254
PyDoc_STR("__replace__($self, /, **changes)\n--\n\n"
254255
"Return a copy of the namespace object with new values for the specified attributes.")},
255-
{NULL, NULL} // sentinel
256+
{"update", (PyCFunction)(void(*)(void))namespace_update,
257+
METH_VARARGS | METH_KEYWORDS,
258+
PyDoc_STR("update(**kwargs)\n--\n\nUpdate namespace attributes from keyword arguments.")
259+
},
260+
256261
};
257262

258263

@@ -321,3 +326,28 @@ _PyNamespace_New(PyObject *kwds)
321326

322327
return (PyObject *)ns;
323328
}
329+
330+
#include "Python.h"
331+
332+
static PyObject *
333+
namespace_update(PyObject *self, PyObject *args, PyObject *kwds)
334+
{
335+
if (kwds == NULL) {
336+
Py_RETURN_NONE;
337+
}
338+
339+
PyObject *dict = PyObject_GetAttrString(self, "__dict__");
340+
if (dict == NULL) {
341+
return NULL;
342+
}
343+
344+
int result = PyDict_Update(dict, kwds);
345+
Py_DECREF(dict);
346+
347+
if (result < 0) {
348+
return NULL;
349+
}
350+
351+
Py_RETURN_NONE;
352+
}
353+

0 commit comments

Comments
 (0)