LCOV - code coverage report
Current view: top level - Objects - interpreteridobject.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 90 101 89.1 %
Date: 2022-07-07 18:19:46 Functions: 12 12 100.0 %

          Line data    Source code
       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         469 : newinterpid(PyTypeObject *cls, int64_t id, int force)
      16             : {
      17         469 :     PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
      18         469 :     if (interp == NULL) {
      19           5 :         if (force) {
      20           4 :             PyErr_Clear();
      21             :         }
      22             :         else {
      23           1 :             return NULL;
      24             :         }
      25             :     }
      26             : 
      27         468 :     if (interp != NULL) {
      28         464 :         if (_PyInterpreterState_IDIncref(interp) < 0) {
      29           0 :             return NULL;
      30             :         }
      31             :     }
      32             : 
      33         468 :     interpid *self = PyObject_New(interpid, cls);
      34         468 :     if (self == NULL) {
      35           0 :         if (interp != NULL) {
      36           0 :             _PyInterpreterState_IDDecref(interp);
      37             :         }
      38           0 :         return NULL;
      39             :     }
      40         468 :     self->id = id;
      41             : 
      42         468 :     return self;
      43             : }
      44             : 
      45             : static int
      46         157 : interp_id_converter(PyObject *arg, void *ptr)
      47             : {
      48             :     int64_t id;
      49         157 :     if (PyObject_TypeCheck(arg, &_PyInterpreterID_Type)) {
      50         126 :         id = ((interpid *)arg)->id;
      51             :     }
      52          31 :     else if (_PyIndex_Check(arg)) {
      53          26 :         id = PyLong_AsLongLong(arg);
      54          26 :         if (id == -1 && PyErr_Occurred()) {
      55           1 :             return 0;
      56             :         }
      57          25 :         if (id < 0) {
      58           7 :             PyErr_Format(PyExc_ValueError,
      59             :                          "interpreter ID must be a non-negative int, got %R", arg);
      60           7 :             return 0;
      61             :         }
      62             :     }
      63             :     else {
      64           5 :         PyErr_Format(PyExc_TypeError,
      65             :                      "interpreter ID must be an int, got %.100s",
      66           5 :                      Py_TYPE(arg)->tp_name);
      67           5 :         return 0;
      68             :     }
      69         144 :     *(int64_t *)ptr = id;
      70         144 :     return 1;
      71             : }
      72             : 
      73             : static PyObject *
      74          12 : interpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds)
      75             : {
      76             :     static char *kwlist[] = {"id", "force", NULL};
      77             :     int64_t id;
      78          12 :     int force = 0;
      79          12 :     if (!PyArg_ParseTupleAndKeywords(args, kwds,
      80             :                                      "O&|$p:InterpreterID.__init__", kwlist,
      81             :                                      interp_id_converter, &id, &force)) {
      82           6 :         return NULL;
      83             :     }
      84             : 
      85           6 :     return (PyObject *)newinterpid(cls, id, force);
      86             : }
      87             : 
      88             : static void
      89         468 : interpid_dealloc(PyObject *v)
      90             : {
      91         468 :     int64_t id = ((interpid *)v)->id;
      92         468 :     PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
      93         468 :     if (interp != NULL) {
      94         393 :         _PyInterpreterState_IDDecref(interp);
      95             :     }
      96             :     else {
      97             :         // already deleted
      98          75 :         PyErr_Clear();
      99             :     }
     100         468 :     Py_TYPE(v)->tp_free(v);
     101         468 : }
     102             : 
     103             : static PyObject *
     104           1 : interpid_repr(PyObject *self)
     105             : {
     106           1 :     PyTypeObject *type = Py_TYPE(self);
     107           1 :     const char *name = _PyType_Name(type);
     108           1 :     interpid *id = (interpid *)self;
     109           1 :     return PyUnicode_FromFormat("%s(%" PRId64 ")", name, id->id);
     110             : }
     111             : 
     112             : static PyObject *
     113          14 : interpid_str(PyObject *self)
     114             : {
     115          14 :     interpid *id = (interpid *)self;
     116          14 :     return PyUnicode_FromFormat("%" PRId64 "", id->id);
     117             : }
     118             : 
     119             : static PyObject *
     120          10 : interpid_int(PyObject *self)
     121             : {
     122          10 :     interpid *id = (interpid *)self;
     123          10 :     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          92 : interpid_hash(PyObject *self)
     168             : {
     169          92 :     interpid *id = (interpid *)self;
     170          92 :     PyObject *obj = PyLong_FromLongLong(id->id);
     171          92 :     if (obj == NULL) {
     172           0 :         return -1;
     173             :     }
     174          92 :     Py_hash_t hash = PyObject_Hash(obj);
     175          92 :     Py_DECREF(obj);
     176          92 :     return hash;
     177             : }
     178             : 
     179             : static PyObject *
     180         357 : interpid_richcompare(PyObject *self, PyObject *other, int op)
     181             : {
     182         357 :     if (op != Py_EQ && op != Py_NE) {
     183           0 :         Py_RETURN_NOTIMPLEMENTED;
     184             :     }
     185             : 
     186         357 :     if (!PyObject_TypeCheck(self, &_PyInterpreterID_Type)) {
     187           0 :         Py_RETURN_NOTIMPLEMENTED;
     188             :     }
     189             : 
     190         357 :     interpid *id = (interpid *)self;
     191             :     int equal;
     192         357 :     if (PyObject_TypeCheck(other, &_PyInterpreterID_Type)) {
     193         142 :         interpid *otherid = (interpid *)other;
     194         142 :         equal = (id->id == otherid->id);
     195             :     }
     196         215 :     else if (PyLong_CheckExact(other)) {
     197             :         /* Fast path */
     198             :         int overflow;
     199         208 :         long long otherid = PyLong_AsLongLongAndOverflow(other, &overflow);
     200         208 :         if (otherid == -1 && PyErr_Occurred()) {
     201           0 :             return NULL;
     202             :         }
     203         208 :         equal = !overflow && (otherid >= 0) && (id->id == otherid);
     204             :     }
     205           7 :     else if (PyNumber_Check(other)) {
     206           4 :         PyObject *pyid = PyLong_FromLongLong(id->id);
     207           4 :         if (pyid == NULL) {
     208           0 :             return NULL;
     209             :         }
     210           4 :         PyObject *res = PyObject_RichCompare(pyid, other, op);
     211           4 :         Py_DECREF(pyid);
     212           4 :         return res;
     213             :     }
     214             :     else {
     215           3 :         Py_RETURN_NOTIMPLEMENTED;
     216             :     }
     217             : 
     218         350 :     if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) {
     219         310 :         Py_RETURN_TRUE;
     220             :     }
     221          40 :     Py_RETURN_FALSE;
     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          20 : PyObject *_PyInterpreterID_New(int64_t id)
     269             : {
     270          20 :     return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
     271             : }
     272             : 
     273             : PyObject *
     274         443 : _PyInterpreterState_GetIDObject(PyInterpreterState *interp)
     275             : {
     276         443 :     if (_PyInterpreterState_IDInitref(interp) != 0) {
     277           0 :         return NULL;
     278             :     };
     279         443 :     int64_t id = PyInterpreterState_GetID(interp);
     280         443 :     if (id < 0) {
     281           0 :         return NULL;
     282             :     }
     283         443 :     return (PyObject *)newinterpid(&_PyInterpreterID_Type, id, 0);
     284             : }
     285             : 
     286             : PyInterpreterState *
     287         145 : _PyInterpreterID_LookUp(PyObject *requested_id)
     288             : {
     289             :     int64_t id;
     290         145 :     if (!interp_id_converter(requested_id, &id)) {
     291           7 :         return NULL;
     292             :     }
     293         138 :     return _PyInterpreterState_LookUpID(id);
     294             : }

Generated by: LCOV version 1.14