Coverage Report

Created: 2022-07-08 09:39

/home/mdboom/Work/builds/cpython/Objects/interpreteridobject.c
Line
Count
Source (jump to first uncovered line)
1
/* InterpreterID object */
2
3
#include "Python.h"
4
#include "pycore_abstract.h"   // _PyIndex_Check()
5
#include "pycore_interp.h"     // _PyInterpreterState_LookUpID()
6
#include "pycore_interpreteridobject.h"
7
8
9
typedef struct interpid {
10
    PyObject_HEAD
11
    int64_t id;
12
} interpid;
13
14
static interpid *
15
newinterpid(PyTypeObject *cls, int64_t id, int force)
16
{
17
    PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
18
    if (interp == NULL) {
  Branch (18:9): [True: 5, False: 464]
19
        if (force) {
  Branch (19:13): [True: 4, False: 1]
20
            PyErr_Clear();
21
        }
22
        else {
23
            return NULL;
24
        }
25
    }
26
27
    if (interp != NULL) {
  Branch (27:9): [True: 464, False: 4]
28
        if (_PyInterpreterState_IDIncref(interp) < 0) {
  Branch (28:13): [True: 0, False: 464]
29
            return NULL;
30
        }
31
    }
32
33
    interpid *self = PyObject_New(interpid, cls);
34
    if (self == NULL) {
  Branch (34:9): [True: 0, False: 468]
35
        if (interp != NULL) {
  Branch (35:13): [True: 0, False: 0]
36
            _PyInterpreterState_IDDecref(interp);
37
        }
38
        return NULL;
39
    }
40
    self->id = id;
41
42
    return self;
43
}
44
45
static int
46
interp_id_converter(PyObject *arg, void *ptr)
47
{
48
    int64_t id;
49
    if (PyObject_TypeCheck(arg, &_PyInterpreterID_Type)) {
50
        id = ((interpid *)arg)->id;
51
    }
52
    else if (_PyIndex_Check(arg)) {
  Branch (52:14): [True: 26, False: 5]
53
        id = PyLong_AsLongLong(arg);
54
        if (id == -1 && 
PyErr_Occurred()8
) {
  Branch (54:13): [True: 8, False: 18]
  Branch (54:25): [True: 1, False: 7]
55
            return 0;
56
        }
57
        if (id < 0) {
  Branch (57:13): [True: 7, False: 18]
58
            PyErr_Format(PyExc_ValueError,
59
                         "interpreter ID must be a non-negative int, got %R", arg);
60
            return 0;
61
        }
62
    }
63
    else {
64
        PyErr_Format(PyExc_TypeError,
65
                     "interpreter ID must be an int, got %.100s",
66
                     Py_TYPE(arg)->tp_name);
67
        return 0;
68
    }
69
    *(int64_t *)ptr = id;
70
    return 1;
71
}
72
73
static PyObject *
74
interpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds)
75
{
76
    static char *kwlist[] = {"id", "force", NULL};
77
    int64_t id;
78
    int force = 0;
79
    if (!PyArg_ParseTupleAndKeywords(args, kwds,
  Branch (79:9): [True: 6, False: 6]
80
                                     "O&|$p:InterpreterID.__init__", kwlist,
81
                                     interp_id_converter, &id, &force)) {
82
        return NULL;
83
    }
84
85
    return (PyObject *)newinterpid(cls, id, force);
86
}
87
88
static void
89
interpid_dealloc(PyObject *v)
90
{
91
    int64_t id = ((interpid *)v)->id;
92
    PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
93
    if (interp != NULL) {
  Branch (93:9): [True: 393, False: 75]
94
        _PyInterpreterState_IDDecref(interp);
95
    }
96
    else {
97
        // already deleted
98
        PyErr_Clear();
99
    }
100
    Py_TYPE(v)->tp_free(v);
101
}
102
103
static PyObject *
104
interpid_repr(PyObject *self)
105
{
106
    PyTypeObject *type = Py_TYPE(self);
107
    const char *name = _PyType_Name(type);
108
    interpid *id = (interpid *)self;
109
    return PyUnicode_FromFormat("%s(%" PRId64 ")", name, id->id);
110
}
111
112
static PyObject *
113
interpid_str(PyObject *self)
114
{
115
    interpid *id = (interpid *)self;
116
    return PyUnicode_FromFormat("%" PRId64 "", id->id);
117
}
118
119
static PyObject *
120
interpid_int(PyObject *self)
121
{
122
    interpid *id = (interpid *)self;
123
    return PyLong_FromLongLong(id->id);
124
}
125
126
static PyNumberMethods interpid_as_number = {
127
     0,                       /* nb_add */
128
     0,                       /* nb_subtract */
129
     0,                       /* nb_multiply */
130
     0,                       /* nb_remainder */
131
     0,                       /* nb_divmod */
132
     0,                       /* nb_power */
133
     0,                       /* nb_negative */
134
     0,                       /* nb_positive */
135
     0,                       /* nb_absolute */
136
     0,                       /* nb_bool */
137
     0,                       /* nb_invert */
138
     0,                       /* nb_lshift */
139
     0,                       /* nb_rshift */
140
     0,                       /* nb_and */
141
     0,                       /* nb_xor */
142
     0,                       /* nb_or */
143
     (unaryfunc)interpid_int, /* nb_int */
144
     0,                       /* nb_reserved */
145
     0,                       /* nb_float */
146
147
     0,                       /* nb_inplace_add */
148
     0,                       /* nb_inplace_subtract */
149
     0,                       /* nb_inplace_multiply */
150
     0,                       /* nb_inplace_remainder */
151
     0,                       /* nb_inplace_power */
152
     0,                       /* nb_inplace_lshift */
153
     0,                       /* nb_inplace_rshift */
154
     0,                       /* nb_inplace_and */
155
     0,                       /* nb_inplace_xor */
156
     0,                       /* nb_inplace_or */
157
158
     0,                       /* nb_floor_divide */
159
     0,                       /* nb_true_divide */
160
     0,                       /* nb_inplace_floor_divide */
161
     0,                       /* nb_inplace_true_divide */
162
163
     (unaryfunc)interpid_int, /* nb_index */
164
};
165
166
static Py_hash_t
167
interpid_hash(PyObject *self)
168
{
169
    interpid *id = (interpid *)self;
170
    PyObject *obj = PyLong_FromLongLong(id->id);
171
    if (obj == NULL) {
  Branch (171:9): [True: 0, False: 92]
172
        return -1;
173
    }
174
    Py_hash_t hash = PyObject_Hash(obj);
175
    Py_DECREF(obj);
176
    return hash;
177
}
178
179
static PyObject *
180
interpid_richcompare(PyObject *self, PyObject *other, int op)
181
{
182
    if (op != Py_EQ && 
op != 5
Py_NE5
) {
  Branch (182:9): [True: 5, False: 352]
  Branch (182:24): [True: 0, False: 5]
183
        Py_RETURN_NOTIMPLEMENTED;
184
    }
185
186
    if (!PyObject_TypeCheck(self, &_PyInterpreterID_Type)) {
  Branch (186:9): [True: 0, False: 357]
187
        Py_RETURN_NOTIMPLEMENTED;
188
    }
189
190
    interpid *id = (interpid *)self;
191
    int equal;
192
    if (PyObject_TypeCheck(other, &_PyInterpreterID_Type)) {
193
        interpid *otherid = (interpid *)other;
194
        equal = (id->id == otherid->id);
195
    }
196
    else if (PyLong_CheckExact(other)) {
197
        /* Fast path */
198
        int overflow;
199
        long long otherid = PyLong_AsLongLongAndOverflow(other, &overflow);
200
        if (otherid == -1 && 
PyErr_Occurred()1
) {
  Branch (200:13): [True: 1, False: 207]
  Branch (200:30): [True: 0, False: 1]
201
            return NULL;
202
        }
203
        equal = !overflow && 
(otherid >= 0)207
&&
(id->id == otherid)207
;
  Branch (203:17): [True: 207, False: 1]
  Branch (203:30): [True: 207, False: 0]
  Branch (203:48): [True: 183, False: 24]
204
    }
205
    else if (PyNumber_Check(other)) {
  Branch (205:14): [True: 4, False: 3]
206
        PyObject *pyid = PyLong_FromLongLong(id->id);
207
        if (pyid == NULL) {
  Branch (207:13): [True: 0, False: 4]
208
            return NULL;
209
        }
210
        PyObject *res = PyObject_RichCompare(pyid, other, op);
211
        Py_DECREF(pyid);
212
        return res;
213
    }
214
    else {
215
        Py_RETURN_NOTIMPLEMENTED;
216
    }
217
218
    if ((op == Py_EQ && 
equal346
) ||
(42
op == 42
Py_NE42
&&
!equal4
)) {
  Branch (218:10): [True: 346, False: 4]
  Branch (218:25): [True: 308, False: 38]
  Branch (218:36): [True: 4, False: 38]
  Branch (218:51): [True: 2, False: 2]
219
        Py_RETURN_TRUE;
220
    }
221
    
Py_RETURN_FALSE40
;
222
}
223
224
PyDoc_STRVAR(interpid_doc,
225
"A interpreter ID identifies a interpreter and may be used as an int.");
226
227
PyTypeObject _PyInterpreterID_Type = {
228
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
229
    "InterpreterID",   /* tp_name */
230
    sizeof(interpid),               /* tp_basicsize */
231
    0,                              /* tp_itemsize */
232
    (destructor)interpid_dealloc,   /* tp_dealloc */
233
    0,                              /* tp_vectorcall_offset */
234
    0,                              /* tp_getattr */
235
    0,                              /* tp_setattr */
236
    0,                              /* tp_as_async */
237
    (reprfunc)interpid_repr,        /* tp_repr */
238
    &interpid_as_number,            /* tp_as_number */
239
    0,                              /* tp_as_sequence */
240
    0,                              /* tp_as_mapping */
241
    interpid_hash,                  /* tp_hash */
242
    0,                              /* tp_call */
243
    (reprfunc)interpid_str,         /* tp_str */
244
    0,                              /* tp_getattro */
245
    0,                              /* tp_setattro */
246
    0,                              /* tp_as_buffer */
247
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
248
    interpid_doc,                   /* tp_doc */
249
    0,                              /* tp_traverse */
250
    0,                              /* tp_clear */
251
    interpid_richcompare,           /* tp_richcompare */
252
    0,                              /* tp_weaklistoffset */
253
    0,                              /* tp_iter */
254
    0,                              /* tp_iternext */
255
    0,                              /* tp_methods */
256
    0,                              /* tp_members */
257
    0,                              /* tp_getset */
258
    0,                              /* tp_base */
259
    0,                              /* tp_dict */
260
    0,                              /* tp_descr_get */
261
    0,                              /* tp_descr_set */
262
    0,                              /* tp_dictoffset */
263
    0,                              /* tp_init */
264
    0,                              /* tp_alloc */
265
    interpid_new,                   /* tp_new */
266
};
267
268
PyObject *_PyInterpreterID_New(int64_t id)
269
{
270
    return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
271
}
272
273
PyObject *
274
_PyInterpreterState_GetIDObject(PyInterpreterState *interp)
275
{
276
    if (_PyInterpreterState_IDInitref(interp) != 0) {
  Branch (276:9): [True: 0, False: 443]
277
        return NULL;
278
    };
279
    int64_t id = PyInterpreterState_GetID(interp);
280
    if (id < 0) {
  Branch (280:9): [True: 0, False: 443]
281
        return NULL;
282
    }
283
    return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
284
}
285
286
PyInterpreterState *
287
_PyInterpreterID_LookUp(PyObject *requested_id)
288
{
289
    int64_t id;
290
    if (!interp_id_converter(requested_id, &id)) {
  Branch (290:9): [True: 7, False: 138]
291
        return NULL;
292
    }
293
    return _PyInterpreterState_LookUpID(id);
294
}