LCOV - code coverage report
Current view: top level - Objects - interpreteridobject.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 90 101 89.1 %
Date: 2022-07-20 13:12:14 Functions: 12 12 100.0 %
Branches: 54 66 81.8 %

           Branch data     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