| 
									
										
										
										
											2016-09-07 14:12:36 -07:00
										 |  |  | // namespace object implementation
 | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2021-10-15 15:21:21 +02:00
										 |  |  | #include "pycore_namespace.h"     // _PyNamespace_Type
 | 
					
						
							| 
									
										
										
										
											2020-04-15 02:35:41 +02:00
										 |  |  | #include "structmember.h"         // PyMemberDef
 | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     PyObject_HEAD | 
					
						
							|  |  |  |     PyObject *ns_dict; | 
					
						
							|  |  |  | } _PyNamespaceObject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMemberDef namespace_members[] = { | 
					
						
							|  |  |  |     {"__dict__", T_OBJECT, offsetof(_PyNamespaceObject, ns_dict), READONLY}, | 
					
						
							|  |  |  |     {NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-07 14:12:36 -07:00
										 |  |  | // Methods
 | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | namespace_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-10-16 22:35:38 -07:00
										 |  |  |     PyObject *self; | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-16 22:35:38 -07:00
										 |  |  |     assert(type != NULL && type->tp_alloc != NULL); | 
					
						
							|  |  |  |     self = type->tp_alloc(type, 0); | 
					
						
							|  |  |  |     if (self != NULL) { | 
					
						
							|  |  |  |         _PyNamespaceObject *ns = (_PyNamespaceObject *)self; | 
					
						
							|  |  |  |         ns->ns_dict = PyDict_New(); | 
					
						
							|  |  |  |         if (ns->ns_dict == NULL) { | 
					
						
							|  |  |  |             Py_DECREF(ns); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-10-16 22:35:38 -07:00
										 |  |  |     return self; | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | namespace_init(_PyNamespaceObject *ns, PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-04-19 20:03:52 +03:00
										 |  |  |     if (PyTuple_GET_SIZE(args) != 0) { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_TypeError, "no positional arguments expected"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-07 22:59:35 +03:00
										 |  |  |     if (kwds == NULL) { | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2017-10-07 22:59:35 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (!PyArg_ValidateKeywordArguments(kwds)) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     return PyDict_Update(ns->ns_dict, kwds); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | namespace_dealloc(_PyNamespaceObject *ns) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject_GC_UnTrack(ns); | 
					
						
							|  |  |  |     Py_CLEAR(ns->ns_dict); | 
					
						
							|  |  |  |     Py_TYPE(ns)->tp_free((PyObject *)ns); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  | namespace_repr(PyObject *ns) | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  | { | 
					
						
							|  |  |  |     int i, loop_error = 0; | 
					
						
							|  |  |  |     PyObject *pairs = NULL, *d = NULL, *keys = NULL, *keys_iter = NULL; | 
					
						
							|  |  |  |     PyObject *key; | 
					
						
							|  |  |  |     PyObject *separator, *pairsrepr, *repr = NULL; | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  |     const char * name; | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 07:15:20 -06:00
										 |  |  |     name = Py_IS_TYPE(ns, &_PyNamespace_Type) ? "namespace" | 
					
						
							| 
									
										
										
										
											2020-02-07 03:04:21 +01:00
										 |  |  |                                                : Py_TYPE(ns)->tp_name; | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     i = Py_ReprEnter(ns); | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     if (i != 0) { | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  |         return i > 0 ? PyUnicode_FromFormat("%s(...)", name) : NULL; | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pairs = PyList_New(0); | 
					
						
							|  |  |  |     if (pairs == NULL) | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d = ((_PyNamespaceObject *)ns)->ns_dict; | 
					
						
							|  |  |  |     assert(d != NULL); | 
					
						
							|  |  |  |     Py_INCREF(d); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     keys = PyDict_Keys(d); | 
					
						
							|  |  |  |     if (keys == NULL) | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     keys_iter = PyObject_GetIter(keys); | 
					
						
							|  |  |  |     if (keys_iter == NULL) | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while ((key = PyIter_Next(keys_iter)) != NULL) { | 
					
						
							| 
									
										
										
										
											2013-11-13 14:17:30 +01:00
										 |  |  |         if (PyUnicode_Check(key) && PyUnicode_GET_LENGTH(key) > 0) { | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |             PyObject *value, *item; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-25 17:59:46 +02:00
										 |  |  |             value = PyDict_GetItemWithError(d, key); | 
					
						
							| 
									
										
										
										
											2018-12-11 08:38:03 +02:00
										 |  |  |             if (value != NULL) { | 
					
						
							| 
									
										
										
										
											2019-02-25 17:59:46 +02:00
										 |  |  |                 item = PyUnicode_FromFormat("%U=%R", key, value); | 
					
						
							| 
									
										
										
										
											2018-12-11 08:38:03 +02:00
										 |  |  |                 if (item == NULL) { | 
					
						
							|  |  |  |                     loop_error = 1; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else { | 
					
						
							|  |  |  |                     loop_error = PyList_Append(pairs, item); | 
					
						
							|  |  |  |                     Py_DECREF(item); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-02-25 17:59:46 +02:00
										 |  |  |             else if (PyErr_Occurred()) { | 
					
						
							|  |  |  |                 loop_error = 1; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_DECREF(key); | 
					
						
							|  |  |  |         if (loop_error) | 
					
						
							|  |  |  |             goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     separator = PyUnicode_FromString(", "); | 
					
						
							|  |  |  |     if (separator == NULL) | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pairsrepr = PyUnicode_Join(separator, pairs); | 
					
						
							|  |  |  |     Py_DECREF(separator); | 
					
						
							|  |  |  |     if (pairsrepr == NULL) | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  |     repr = PyUnicode_FromFormat("%s(%S)", name, pairsrepr); | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     Py_DECREF(pairsrepr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  |     Py_XDECREF(pairs); | 
					
						
							|  |  |  |     Py_XDECREF(d); | 
					
						
							|  |  |  |     Py_XDECREF(keys); | 
					
						
							|  |  |  |     Py_XDECREF(keys_iter); | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  |     Py_ReprLeave(ns); | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return repr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | namespace_traverse(_PyNamespaceObject *ns, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_VISIT(ns->ns_dict); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | namespace_clear(_PyNamespaceObject *ns) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_CLEAR(ns->ns_dict); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | namespace_richcompare(PyObject *self, PyObject *other, int op) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-22 11:02:49 +03:00
										 |  |  |     if (PyObject_TypeCheck(self, &_PyNamespace_Type) && | 
					
						
							|  |  |  |         PyObject_TypeCheck(other, &_PyNamespace_Type)) | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  |         return PyObject_RichCompare(((_PyNamespaceObject *)self)->ns_dict, | 
					
						
							|  |  |  |                                    ((_PyNamespaceObject *)other)->ns_dict, op); | 
					
						
							| 
									
										
										
										
											2015-05-22 11:02:49 +03:00
										 |  |  |     Py_RETURN_NOTIMPLEMENTED; | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-16 18:20:32 -07:00
										 |  |  | PyDoc_STRVAR(namespace_reduce__doc__, "Return state information for pickling"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2018-04-30 00:29:33 +05:30
										 |  |  | namespace_reduce(_PyNamespaceObject *ns, PyObject *Py_UNUSED(ignored)) | 
					
						
							| 
									
										
										
										
											2013-02-16 18:20:32 -07:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject *result, *args = PyTuple_New(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!args) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = PyTuple_Pack(3, (PyObject *)Py_TYPE(ns), args, ns->ns_dict); | 
					
						
							|  |  |  |     Py_DECREF(args); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMethodDef namespace_methods[] = { | 
					
						
							|  |  |  |     {"__reduce__", (PyCFunction)namespace_reduce, METH_NOARGS, | 
					
						
							|  |  |  |      namespace_reduce__doc__}, | 
					
						
							| 
									
										
										
										
											2016-09-07 14:12:36 -07:00
										 |  |  |     {NULL,         NULL}  // sentinel
 | 
					
						
							| 
									
										
										
										
											2013-02-16 18:20:32 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  | PyDoc_STRVAR(namespace_doc, | 
					
						
							|  |  |  | "A simple attribute-based namespace.\n\
 | 
					
						
							|  |  |  | \n\ | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  | SimpleNamespace(**kwargs)"); | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject _PyNamespace_Type = { | 
					
						
							|  |  |  |     PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  |     "types.SimpleNamespace",                    /* tp_name */ | 
					
						
							| 
									
										
										
										
											2018-09-10 18:46:08 +02:00
										 |  |  |     sizeof(_PyNamespaceObject),                 /* tp_basicsize */ | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     0,                                          /* tp_itemsize */ | 
					
						
							|  |  |  |     (destructor)namespace_dealloc,              /* tp_dealloc */ | 
					
						
							| 
									
										
										
										
											2019-05-31 04:13:39 +02:00
										 |  |  |     0,                                          /* tp_vectorcall_offset */ | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     0,                                          /* tp_getattr */ | 
					
						
							|  |  |  |     0,                                          /* tp_setattr */ | 
					
						
							| 
									
										
										
										
											2019-05-31 04:13:39 +02:00
										 |  |  |     0,                                          /* tp_as_async */ | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     (reprfunc)namespace_repr,                   /* tp_repr */ | 
					
						
							|  |  |  |     0,                                          /* tp_as_number */ | 
					
						
							|  |  |  |     0,                                          /* tp_as_sequence */ | 
					
						
							|  |  |  |     0,                                          /* tp_as_mapping */ | 
					
						
							|  |  |  |     0,                                          /* tp_hash */ | 
					
						
							|  |  |  |     0,                                          /* tp_call */ | 
					
						
							|  |  |  |     0,                                          /* tp_str */ | 
					
						
							|  |  |  |     PyObject_GenericGetAttr,                    /* tp_getattro */ | 
					
						
							|  |  |  |     PyObject_GenericSetAttr,                    /* tp_setattro */ | 
					
						
							|  |  |  |     0,                                          /* tp_as_buffer */ | 
					
						
							|  |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | | 
					
						
							|  |  |  |         Py_TPFLAGS_BASETYPE,                    /* tp_flags */ | 
					
						
							|  |  |  |     namespace_doc,                              /* tp_doc */ | 
					
						
							|  |  |  |     (traverseproc)namespace_traverse,           /* tp_traverse */ | 
					
						
							|  |  |  |     (inquiry)namespace_clear,                   /* tp_clear */ | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  |     namespace_richcompare,                      /* tp_richcompare */ | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     0,                                          /* tp_weaklistoffset */ | 
					
						
							|  |  |  |     0,                                          /* tp_iter */ | 
					
						
							|  |  |  |     0,                                          /* tp_iternext */ | 
					
						
							| 
									
										
										
										
											2013-02-16 18:20:32 -07:00
										 |  |  |     namespace_methods,                          /* tp_methods */ | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     namespace_members,                          /* tp_members */ | 
					
						
							|  |  |  |     0,                                          /* tp_getset */ | 
					
						
							|  |  |  |     0,                                          /* tp_base */ | 
					
						
							|  |  |  |     0,                                          /* tp_dict */ | 
					
						
							|  |  |  |     0,                                          /* tp_descr_get */ | 
					
						
							|  |  |  |     0,                                          /* tp_descr_set */ | 
					
						
							|  |  |  |     offsetof(_PyNamespaceObject, ns_dict),      /* tp_dictoffset */ | 
					
						
							|  |  |  |     (initproc)namespace_init,                   /* tp_init */ | 
					
						
							|  |  |  |     PyType_GenericAlloc,                        /* tp_alloc */ | 
					
						
							|  |  |  |     (newfunc)namespace_new,                     /* tp_new */ | 
					
						
							|  |  |  |     PyObject_GC_Del,                            /* tp_free */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _PyNamespace_New(PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *ns = namespace_new(&_PyNamespace_Type, NULL, NULL); | 
					
						
							|  |  |  |     if (ns == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (kwds == NULL) | 
					
						
							|  |  |  |         return ns; | 
					
						
							|  |  |  |     if (PyDict_Update(((_PyNamespaceObject *)ns)->ns_dict, kwds) != 0) { | 
					
						
							|  |  |  |         Py_DECREF(ns); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return (PyObject *)ns; | 
					
						
							|  |  |  | } |