/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 | } |