Coverage Report

Created: 2025-07-11 06:59

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