summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Objects/namespaceobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/Objects/namespaceobject.c')
-rw-r--r--contrib/tools/python3/Objects/namespaceobject.c82
1 files changed, 72 insertions, 10 deletions
diff --git a/contrib/tools/python3/Objects/namespaceobject.c b/contrib/tools/python3/Objects/namespaceobject.c
index 7082c6fd465..4b1d625fc78 100644
--- a/contrib/tools/python3/Objects/namespaceobject.c
+++ b/contrib/tools/python3/Objects/namespaceobject.c
@@ -1,8 +1,10 @@
// namespace object implementation
#include "Python.h"
+#include "pycore_modsupport.h" // _PyArg_NoPositional()
#include "pycore_namespace.h" // _PyNamespace_Type
-#include "structmember.h" // PyMemberDef
+
+#include <stddef.h> // offsetof()
typedef struct {
@@ -10,9 +12,12 @@ typedef struct {
PyObject *ns_dict;
} _PyNamespaceObject;
+#define _PyNamespace_CAST(op) _Py_CAST(_PyNamespaceObject*, (op))
+#define _PyNamespace_Check(op) PyObject_TypeCheck((op), &_PyNamespace_Type)
+
static PyMemberDef namespace_members[] = {
- {"__dict__", T_OBJECT, offsetof(_PyNamespaceObject, ns_dict), READONLY},
+ {"__dict__", _Py_T_OBJECT, offsetof(_PyNamespaceObject, ns_dict), Py_READONLY},
{NULL}
};
@@ -41,10 +46,28 @@ namespace_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static int
namespace_init(_PyNamespaceObject *ns, PyObject *args, PyObject *kwds)
{
- if (PyTuple_GET_SIZE(args) != 0) {
- PyErr_Format(PyExc_TypeError, "no positional arguments expected");
+ PyObject *arg = NULL;
+ if (!PyArg_UnpackTuple(args, _PyType_Name(Py_TYPE(ns)), 0, 1, &arg)) {
return -1;
}
+ if (arg != NULL) {
+ PyObject *dict;
+ if (PyDict_CheckExact(arg)) {
+ dict = Py_NewRef(arg);
+ }
+ else {
+ dict = PyObject_CallOneArg((PyObject *)&PyDict_Type, arg);
+ if (dict == NULL) {
+ return -1;
+ }
+ }
+ int err = (!PyArg_ValidateKeywordArguments(dict) ||
+ PyDict_Update(ns->ns_dict, dict) < 0);
+ Py_DECREF(dict);
+ if (err) {
+ return -1;
+ }
+ }
if (kwds == NULL) {
return 0;
}
@@ -100,9 +123,10 @@ namespace_repr(PyObject *ns)
if (PyUnicode_Check(key) && PyUnicode_GET_LENGTH(key) > 0) {
PyObject *value, *item;
- value = PyDict_GetItemWithError(d, key);
- if (value != NULL) {
+ int has_key = PyDict_GetItemRef(d, key, &value);
+ if (has_key == 1) {
item = PyUnicode_FromFormat("%U=%R", key, value);
+ Py_DECREF(value);
if (item == NULL) {
loop_error = 1;
}
@@ -111,7 +135,7 @@ namespace_repr(PyObject *ns)
Py_DECREF(item);
}
}
- else if (PyErr_Occurred()) {
+ else if (has_key < 0) {
loop_error = 1;
}
}
@@ -191,17 +215,55 @@ 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 (!_PyNamespace_Check(result)) {
+ PyErr_Format(PyExc_TypeError,
+ "expect %N type, but %T() returned '%T' object",
+ &_PyNamespace_Type, self, result);
+ Py_DECREF(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,
+ PyDoc_STR("__replace__($self, /, **changes)\n--\n\n"
+ "Return a copy of the namespace object with new values for the specified attributes.")},
{NULL, NULL} // sentinel
};
PyDoc_STRVAR(namespace_doc,
-"A simple attribute-based namespace.\n\
-\n\
-SimpleNamespace(**kwargs)");
+"SimpleNamespace(mapping_or_iterable=(), /, **kwargs)\n\
+--\n\n\
+A simple attribute-based namespace.");
PyTypeObject _PyNamespace_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)