| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  | /* namespace object implementation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Python.h"
 | 
					
						
							|  |  |  | #include "structmember.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  |     PyObject_HEAD | 
					
						
							|  |  |  |     PyObject *ns_dict; | 
					
						
							|  |  |  | } _PyNamespaceObject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMemberDef namespace_members[] = { | 
					
						
							|  |  |  |     {"__dict__", T_OBJECT, offsetof(_PyNamespaceObject, ns_dict), READONLY}, | 
					
						
							|  |  |  |     {NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Methods */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* ignore args if it's NULL or empty */ | 
					
						
							|  |  |  |     if (args != NULL) { | 
					
						
							|  |  |  |         Py_ssize_t argcount = PyObject_Size(args); | 
					
						
							|  |  |  |         if (argcount < 0) | 
					
						
							| 
									
										
										
										
											2013-06-05 00:13:51 +02:00
										 |  |  |             return -1; | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |         else if (argcount > 0) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, "no positional arguments expected"); | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (kwds == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-16 16:32:39 -07:00
										 |  |  |     name = (Py_TYPE(ns) == &_PyNamespace_Type) ? "namespace" | 
					
						
							|  |  |  |                                                : ns->ob_type->tp_name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  |     if (PyList_Sort(keys) != 0) | 
					
						
							|  |  |  |         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; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             value = PyDict_GetItem(d, key); | 
					
						
							|  |  |  |             assert(value != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             item = PyUnicode_FromFormat("%S=%R", key, value); | 
					
						
							|  |  |  |             if (item == NULL) { | 
					
						
							|  |  |  |                 loop_error = 1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 loop_error = PyList_Append(pairs, item); | 
					
						
							|  |  |  |                 Py_DECREF(item); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (PyObject_IsInstance(self, (PyObject *)&_PyNamespace_Type) && | 
					
						
							|  |  |  |             PyObject_IsInstance(other, (PyObject *)&_PyNamespace_Type)) | 
					
						
							|  |  |  |         return PyObject_RichCompare(((_PyNamespaceObject *)self)->ns_dict, | 
					
						
							|  |  |  |                                    ((_PyNamespaceObject *)other)->ns_dict, op); | 
					
						
							|  |  |  |     Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  |     return Py_NotImplemented; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-16 18:20:32 -07:00
										 |  |  | PyDoc_STRVAR(namespace_reduce__doc__, "Return state information for pickling"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2013-08-13 20:18:52 +02:00
										 |  |  | namespace_reduce(_PyNamespaceObject *ns) | 
					
						
							| 
									
										
										
										
											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__}, | 
					
						
							|  |  |  |     {NULL,         NULL}  /* sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 */ | 
					
						
							| 
									
										
										
										
											2012-06-03 16:18:47 -04:00
										 |  |  |     sizeof(_PyNamespaceObject),                 /* tp_size */ | 
					
						
							|  |  |  |     0,                                          /* tp_itemsize */ | 
					
						
							|  |  |  |     (destructor)namespace_dealloc,              /* tp_dealloc */ | 
					
						
							|  |  |  |     0,                                          /* tp_print */ | 
					
						
							|  |  |  |     0,                                          /* tp_getattr */ | 
					
						
							|  |  |  |     0,                                          /* tp_setattr */ | 
					
						
							|  |  |  |     0,                                          /* tp_reserved */ | 
					
						
							|  |  |  |     (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; | 
					
						
							|  |  |  | } |