Coverage Report

Created: 2022-07-08 09:39

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