/src/Python-3.8.3/Objects/namespaceobject.c
Line  | Count  | Source  | 
1  |  | // namespace object implementation  | 
2  |  |  | 
3  |  | #include "Python.h"  | 
4  |  | #include "structmember.h"  | 
5  |  |  | 
6  |  |  | 
7  |  | typedef struct { | 
8  |  |     PyObject_HEAD  | 
9  |  |     PyObject *ns_dict;  | 
10  |  | } _PyNamespaceObject;  | 
11  |  |  | 
12  |  |  | 
13  |  | static PyMemberDef namespace_members[] = { | 
14  |  |     {"__dict__", T_OBJECT, offsetof(_PyNamespaceObject, ns_dict), READONLY}, | 
15  |  |     {NULL} | 
16  |  | };  | 
17  |  |  | 
18  |  |  | 
19  |  | // Methods  | 
20  |  |  | 
21  |  | static PyObject *  | 
22  |  | namespace_new(PyTypeObject *type, PyObject *args, PyObject *kwds)  | 
23  | 14  | { | 
24  | 14  |     PyObject *self;  | 
25  |  |  | 
26  | 14  |     assert(type != NULL && type->tp_alloc != NULL);  | 
27  | 14  |     self = type->tp_alloc(type, 0);  | 
28  | 14  |     if (self != NULL) { | 
29  | 14  |         _PyNamespaceObject *ns = (_PyNamespaceObject *)self;  | 
30  | 14  |         ns->ns_dict = PyDict_New();  | 
31  | 14  |         if (ns->ns_dict == NULL) { | 
32  | 0  |             Py_DECREF(ns);  | 
33  | 0  |             return NULL;  | 
34  | 0  |         }  | 
35  | 14  |     }  | 
36  | 14  |     return self;  | 
37  | 14  | }  | 
38  |  |  | 
39  |  |  | 
40  |  | static int  | 
41  |  | namespace_init(_PyNamespaceObject *ns, PyObject *args, PyObject *kwds)  | 
42  | 0  | { | 
43  | 0  |     if (PyTuple_GET_SIZE(args) != 0) { | 
44  | 0  |         PyErr_Format(PyExc_TypeError, "no positional arguments expected");  | 
45  | 0  |         return -1;  | 
46  | 0  |     }  | 
47  | 0  |     if (kwds == NULL) { | 
48  | 0  |         return 0;  | 
49  | 0  |     }  | 
50  | 0  |     if (!PyArg_ValidateKeywordArguments(kwds)) { | 
51  | 0  |         return -1;  | 
52  | 0  |     }  | 
53  | 0  |     return PyDict_Update(ns->ns_dict, kwds);  | 
54  | 0  | }  | 
55  |  |  | 
56  |  |  | 
57  |  | static void  | 
58  |  | namespace_dealloc(_PyNamespaceObject *ns)  | 
59  | 0  | { | 
60  | 0  |     PyObject_GC_UnTrack(ns);  | 
61  | 0  |     Py_CLEAR(ns->ns_dict);  | 
62  | 0  |     Py_TYPE(ns)->tp_free((PyObject *)ns);  | 
63  | 0  | }  | 
64  |  |  | 
65  |  |  | 
66  |  | static PyObject *  | 
67  |  | namespace_repr(PyObject *ns)  | 
68  | 0  | { | 
69  | 0  |     int i, loop_error = 0;  | 
70  | 0  |     PyObject *pairs = NULL, *d = NULL, *keys = NULL, *keys_iter = NULL;  | 
71  | 0  |     PyObject *key;  | 
72  | 0  |     PyObject *separator, *pairsrepr, *repr = NULL;  | 
73  | 0  |     const char * name;  | 
74  |  | 
  | 
75  | 0  |     name = (Py_TYPE(ns) == &_PyNamespace_Type) ? "namespace"  | 
76  | 0  |                                                : ns->ob_type->tp_name;  | 
77  |  | 
  | 
78  | 0  |     i = Py_ReprEnter(ns);  | 
79  | 0  |     if (i != 0) { | 
80  | 0  |         return i > 0 ? PyUnicode_FromFormat("%s(...)", name) : NULL; | 
81  | 0  |     }  | 
82  |  |  | 
83  | 0  |     pairs = PyList_New(0);  | 
84  | 0  |     if (pairs == NULL)  | 
85  | 0  |         goto error;  | 
86  |  |  | 
87  | 0  |     d = ((_PyNamespaceObject *)ns)->ns_dict;  | 
88  | 0  |     assert(d != NULL);  | 
89  | 0  |     Py_INCREF(d);  | 
90  |  | 
  | 
91  | 0  |     keys = PyDict_Keys(d);  | 
92  | 0  |     if (keys == NULL)  | 
93  | 0  |         goto error;  | 
94  | 0  |     if (PyList_Sort(keys) != 0)  | 
95  | 0  |         goto error;  | 
96  |  |  | 
97  | 0  |     keys_iter = PyObject_GetIter(keys);  | 
98  | 0  |     if (keys_iter == NULL)  | 
99  | 0  |         goto error;  | 
100  |  |  | 
101  | 0  |     while ((key = PyIter_Next(keys_iter)) != NULL) { | 
102  | 0  |         if (PyUnicode_Check(key) && PyUnicode_GET_LENGTH(key) > 0) { | 
103  | 0  |             PyObject *value, *item;  | 
104  |  | 
  | 
105  | 0  |             value = PyDict_GetItemWithError(d, key);  | 
106  | 0  |             if (value != NULL) { | 
107  | 0  |                 item = PyUnicode_FromFormat("%U=%R", key, value); | 
108  | 0  |                 if (item == NULL) { | 
109  | 0  |                     loop_error = 1;  | 
110  | 0  |                 }  | 
111  | 0  |                 else { | 
112  | 0  |                     loop_error = PyList_Append(pairs, item);  | 
113  | 0  |                     Py_DECREF(item);  | 
114  | 0  |                 }  | 
115  | 0  |             }  | 
116  | 0  |             else if (PyErr_Occurred()) { | 
117  | 0  |                 loop_error = 1;  | 
118  | 0  |             }  | 
119  | 0  |         }  | 
120  |  | 
  | 
121  | 0  |         Py_DECREF(key);  | 
122  | 0  |         if (loop_error)  | 
123  | 0  |             goto error;  | 
124  | 0  |     }  | 
125  |  |  | 
126  | 0  |     separator = PyUnicode_FromString(", "); | 
127  | 0  |     if (separator == NULL)  | 
128  | 0  |         goto error;  | 
129  |  |  | 
130  | 0  |     pairsrepr = PyUnicode_Join(separator, pairs);  | 
131  | 0  |     Py_DECREF(separator);  | 
132  | 0  |     if (pairsrepr == NULL)  | 
133  | 0  |         goto error;  | 
134  |  |  | 
135  | 0  |     repr = PyUnicode_FromFormat("%s(%S)", name, pairsrepr); | 
136  | 0  |     Py_DECREF(pairsrepr);  | 
137  |  | 
  | 
138  | 0  | error:  | 
139  | 0  |     Py_XDECREF(pairs);  | 
140  | 0  |     Py_XDECREF(d);  | 
141  | 0  |     Py_XDECREF(keys);  | 
142  | 0  |     Py_XDECREF(keys_iter);  | 
143  | 0  |     Py_ReprLeave(ns);  | 
144  |  | 
  | 
145  | 0  |     return repr;  | 
146  | 0  | }  | 
147  |  |  | 
148  |  |  | 
149  |  | static int  | 
150  |  | namespace_traverse(_PyNamespaceObject *ns, visitproc visit, void *arg)  | 
151  | 30  | { | 
152  | 30  |     Py_VISIT(ns->ns_dict);  | 
153  | 30  |     return 0;  | 
154  | 30  | }  | 
155  |  |  | 
156  |  |  | 
157  |  | static int  | 
158  |  | namespace_clear(_PyNamespaceObject *ns)  | 
159  | 0  | { | 
160  | 0  |     Py_CLEAR(ns->ns_dict);  | 
161  | 0  |     return 0;  | 
162  | 0  | }  | 
163  |  |  | 
164  |  |  | 
165  |  | static PyObject *  | 
166  |  | namespace_richcompare(PyObject *self, PyObject *other, int op)  | 
167  | 0  | { | 
168  | 0  |     if (PyObject_TypeCheck(self, &_PyNamespace_Type) &&  | 
169  | 0  |         PyObject_TypeCheck(other, &_PyNamespace_Type))  | 
170  | 0  |         return PyObject_RichCompare(((_PyNamespaceObject *)self)->ns_dict,  | 
171  | 0  |                                    ((_PyNamespaceObject *)other)->ns_dict, op);  | 
172  | 0  |     Py_RETURN_NOTIMPLEMENTED;  | 
173  | 0  | }  | 
174  |  |  | 
175  |  |  | 
176  |  | PyDoc_STRVAR(namespace_reduce__doc__, "Return state information for pickling");  | 
177  |  |  | 
178  |  | static PyObject *  | 
179  |  | namespace_reduce(_PyNamespaceObject *ns, PyObject *Py_UNUSED(ignored))  | 
180  | 0  | { | 
181  | 0  |     PyObject *result, *args = PyTuple_New(0);  | 
182  |  | 
  | 
183  | 0  |     if (!args)  | 
184  | 0  |         return NULL;  | 
185  |  |  | 
186  | 0  |     result = PyTuple_Pack(3, (PyObject *)Py_TYPE(ns), args, ns->ns_dict);  | 
187  | 0  |     Py_DECREF(args);  | 
188  | 0  |     return result;  | 
189  | 0  | }  | 
190  |  |  | 
191  |  |  | 
192  |  | static PyMethodDef namespace_methods[] = { | 
193  |  |     {"__reduce__", (PyCFunction)namespace_reduce, METH_NOARGS, | 
194  |  |      namespace_reduce__doc__},  | 
195  |  |     {NULL,         NULL}  // sentinel | 
196  |  | };  | 
197  |  |  | 
198  |  |  | 
199  |  | PyDoc_STRVAR(namespace_doc,  | 
200  |  | "A simple attribute-based namespace.\n\  | 
201  |  | \n\  | 
202  |  | SimpleNamespace(**kwargs)");  | 
203  |  |  | 
204  |  | PyTypeObject _PyNamespace_Type = { | 
205  |  |     PyVarObject_HEAD_INIT(&PyType_Type, 0)  | 
206  |  |     "types.SimpleNamespace",                    /* tp_name */  | 
207  |  |     sizeof(_PyNamespaceObject),                 /* tp_basicsize */  | 
208  |  |     0,                                          /* tp_itemsize */  | 
209  |  |     (destructor)namespace_dealloc,              /* tp_dealloc */  | 
210  |  |     0,                                          /* tp_vectorcall_offset */  | 
211  |  |     0,                                          /* tp_getattr */  | 
212  |  |     0,                                          /* tp_setattr */  | 
213  |  |     0,                                          /* tp_as_async */  | 
214  |  |     (reprfunc)namespace_repr,                   /* tp_repr */  | 
215  |  |     0,                                          /* tp_as_number */  | 
216  |  |     0,                                          /* tp_as_sequence */  | 
217  |  |     0,                                          /* tp_as_mapping */  | 
218  |  |     0,                                          /* tp_hash */  | 
219  |  |     0,                                          /* tp_call */  | 
220  |  |     0,                                          /* tp_str */  | 
221  |  |     PyObject_GenericGetAttr,                    /* tp_getattro */  | 
222  |  |     PyObject_GenericSetAttr,                    /* tp_setattro */  | 
223  |  |     0,                                          /* tp_as_buffer */  | 
224  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |  | 
225  |  |         Py_TPFLAGS_BASETYPE,                    /* tp_flags */  | 
226  |  |     namespace_doc,                              /* tp_doc */  | 
227  |  |     (traverseproc)namespace_traverse,           /* tp_traverse */  | 
228  |  |     (inquiry)namespace_clear,                   /* tp_clear */  | 
229  |  |     namespace_richcompare,                      /* tp_richcompare */  | 
230  |  |     0,                                          /* tp_weaklistoffset */  | 
231  |  |     0,                                          /* tp_iter */  | 
232  |  |     0,                                          /* tp_iternext */  | 
233  |  |     namespace_methods,                          /* tp_methods */  | 
234  |  |     namespace_members,                          /* tp_members */  | 
235  |  |     0,                                          /* tp_getset */  | 
236  |  |     0,                                          /* tp_base */  | 
237  |  |     0,                                          /* tp_dict */  | 
238  |  |     0,                                          /* tp_descr_get */  | 
239  |  |     0,                                          /* tp_descr_set */  | 
240  |  |     offsetof(_PyNamespaceObject, ns_dict),      /* tp_dictoffset */  | 
241  |  |     (initproc)namespace_init,                   /* tp_init */  | 
242  |  |     PyType_GenericAlloc,                        /* tp_alloc */  | 
243  |  |     (newfunc)namespace_new,                     /* tp_new */  | 
244  |  |     PyObject_GC_Del,                            /* tp_free */  | 
245  |  | };  | 
246  |  |  | 
247  |  |  | 
248  |  | PyObject *  | 
249  |  | _PyNamespace_New(PyObject *kwds)  | 
250  | 14  | { | 
251  | 14  |     PyObject *ns = namespace_new(&_PyNamespace_Type, NULL, NULL);  | 
252  | 14  |     if (ns == NULL)  | 
253  | 0  |         return NULL;  | 
254  |  |  | 
255  | 14  |     if (kwds == NULL)  | 
256  | 0  |         return ns;  | 
257  | 14  |     if (PyDict_Update(((_PyNamespaceObject *)ns)->ns_dict, kwds) != 0) { | 
258  | 0  |         Py_DECREF(ns);  | 
259  | 0  |         return NULL;  | 
260  | 0  |     }  | 
261  |  |  | 
262  | 14  |     return (PyObject *)ns;  | 
263  | 14  | }  |