diff options
Diffstat (limited to 'contrib/tools/python3/Objects/namespaceobject.c')
| -rw-r--r-- | contrib/tools/python3/Objects/namespaceobject.c | 82 |
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) |
