LCOV - code coverage report
Current view: top level - Modules/_sqlite - microprotocols.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 43 50 86.0 %
Date: 2022-07-20 13:12:14 Functions: 3 3 100.0 %
Branches: 23 32 71.9 %

           Branch data     Line data    Source code
       1                 :            : /* microprotocols.c - minimalist and non-validating protocols implementation
       2                 :            :  *
       3                 :            :  * Copyright (C) 2003-2004 Federico Di Gregorio <fog@debian.org>
       4                 :            :  *
       5                 :            :  * This file is part of psycopg and was adapted for pysqlite. Federico Di
       6                 :            :  * Gregorio gave the permission to use it within pysqlite under the following
       7                 :            :  * license:
       8                 :            :  *
       9                 :            :  * This software is provided 'as-is', without any express or implied
      10                 :            :  * warranty.  In no event will the authors be held liable for any damages
      11                 :            :  * arising from the use of this software.
      12                 :            :  *
      13                 :            :  * Permission is granted to anyone to use this software for any purpose,
      14                 :            :  * including commercial applications, and to alter it and redistribute it
      15                 :            :  * freely, subject to the following restrictions:
      16                 :            :  *
      17                 :            :  * 1. The origin of this software must not be misrepresented; you must not
      18                 :            :  *    claim that you wrote the original software. If you use this software
      19                 :            :  *    in a product, an acknowledgment in the product documentation would be
      20                 :            :  *    appreciated but is not required.
      21                 :            :  * 2. Altered source versions must be plainly marked as such, and must not be
      22                 :            :  *    misrepresented as being the original software.
      23                 :            :  * 3. This notice may not be removed or altered from any source distribution.
      24                 :            :  */
      25                 :            : 
      26                 :            : #include <Python.h>
      27                 :            : 
      28                 :            : #include "cursor.h"
      29                 :            : #include "microprotocols.h"
      30                 :            : #include "prepare_protocol.h"
      31                 :            : 
      32                 :            : 
      33                 :            : /* pysqlite_microprotocols_init - initialize the adapters dictionary */
      34                 :            : 
      35                 :            : int
      36                 :          5 : pysqlite_microprotocols_init(PyObject *module)
      37                 :            : {
      38                 :            :     /* create adapters dictionary and put it in module namespace */
      39                 :          5 :     pysqlite_state *state = pysqlite_get_state(module);
      40                 :          5 :     state->psyco_adapters = PyDict_New();
      41         [ -  + ]:          5 :     if (state->psyco_adapters == NULL) {
      42                 :          0 :         return -1;
      43                 :            :     }
      44                 :            : 
      45                 :          5 :     return PyModule_AddObjectRef(module, "adapters", state->psyco_adapters);
      46                 :            : }
      47                 :            : 
      48                 :            : 
      49                 :            : /* pysqlite_microprotocols_add - add a reverse type-caster to the dictionary */
      50                 :            : 
      51                 :            : int
      52                 :         17 : pysqlite_microprotocols_add(pysqlite_state *state, PyTypeObject *type,
      53                 :            :                             PyObject *proto, PyObject *cast)
      54                 :            : {
      55                 :            :     PyObject* key;
      56                 :            :     int rc;
      57                 :            : 
      58                 :            :     assert(type != NULL);
      59                 :            :     assert(proto != NULL);
      60                 :         17 :     key = PyTuple_Pack(2, (PyObject *)type, proto);
      61         [ -  + ]:         17 :     if (!key) {
      62                 :          0 :         return -1;
      63                 :            :     }
      64                 :            : 
      65                 :         17 :     rc = PyDict_SetItem(state->psyco_adapters, key, cast);
      66                 :         17 :     Py_DECREF(key);
      67                 :            : 
      68                 :         17 :     return rc;
      69                 :            : }
      70                 :            : 
      71                 :            : /* pysqlite_microprotocols_adapt - adapt an object to the built-in protocol */
      72                 :            : 
      73                 :            : PyObject *
      74                 :        291 : pysqlite_microprotocols_adapt(pysqlite_state *state, PyObject *obj,
      75                 :            :                               PyObject *proto, PyObject *alt)
      76                 :            : {
      77                 :            :     PyObject *adapter, *key, *adapted;
      78                 :            : 
      79                 :            :     /* we don't check for exact type conformance as specified in PEP 246
      80                 :            :        because the PrepareProtocolType type is abstract and there is no
      81                 :            :        way to get a quotable object to be its instance */
      82                 :            : 
      83                 :            :     /* look for an adapter in the registry */
      84                 :        291 :     key = PyTuple_Pack(2, (PyObject *)Py_TYPE(obj), proto);
      85         [ -  + ]:        291 :     if (!key) {
      86                 :          0 :         return NULL;
      87                 :            :     }
      88                 :        291 :     adapter = PyDict_GetItemWithError(state->psyco_adapters, key);
      89                 :        291 :     Py_DECREF(key);
      90         [ +  + ]:        291 :     if (adapter) {
      91                 :          7 :         Py_INCREF(adapter);
      92                 :          7 :         adapted = PyObject_CallOneArg(adapter, obj);
      93                 :          7 :         Py_DECREF(adapter);
      94                 :          7 :         return adapted;
      95                 :            :     }
      96         [ -  + ]:        284 :     if (PyErr_Occurred()) {
      97                 :          0 :         return NULL;
      98                 :            :     }
      99                 :            : 
     100                 :            :     /* try to have the protocol adapt this object */
     101         [ -  + ]:        284 :     if (_PyObject_LookupAttr(proto, state->str___adapt__, &adapter) < 0) {
     102                 :          0 :         return NULL;
     103                 :            :     }
     104         [ +  + ]:        284 :     if (adapter) {
     105                 :          2 :         adapted = PyObject_CallOneArg(adapter, obj);
     106                 :          2 :         Py_DECREF(adapter);
     107                 :            : 
     108         [ +  + ]:          2 :         if (adapted == Py_None) {
     109                 :          1 :             Py_DECREF(adapted);
     110                 :            :         }
     111   [ -  +  -  - ]:          1 :         else if (adapted || !PyErr_ExceptionMatches(PyExc_TypeError)) {
     112                 :          1 :             return adapted;
     113                 :            :         }
     114                 :            :         else {
     115                 :          0 :             PyErr_Clear();
     116                 :            :         }
     117                 :            :     }
     118                 :            : 
     119                 :            :     /* and finally try to have the object adapt itself */
     120         [ -  + ]:        283 :     if (_PyObject_LookupAttr(obj, state->str___conform__, &adapter) < 0) {
     121                 :          0 :         return NULL;
     122                 :            :     }
     123         [ +  + ]:        283 :     if (adapter) {
     124                 :          7 :         adapted = PyObject_CallOneArg(adapter, proto);
     125                 :          7 :         Py_DECREF(adapter);
     126                 :            : 
     127         [ +  + ]:          7 :         if (adapted == Py_None) {
     128                 :          1 :             Py_DECREF(adapted);
     129                 :            :         }
     130   [ +  +  +  + ]:          6 :         else if (adapted || !PyErr_ExceptionMatches(PyExc_TypeError)) {
     131                 :          4 :             return adapted;
     132                 :            :         }
     133                 :            :         else {
     134                 :          2 :             PyErr_Clear();
     135                 :            :         }
     136                 :            :     }
     137                 :            : 
     138         [ +  + ]:        279 :     if (alt) {
     139                 :        275 :         return Py_NewRef(alt);
     140                 :            :     }
     141                 :            :     /* else set the right exception and return NULL */
     142                 :          4 :     PyErr_SetString(state->ProgrammingError, "can't adapt");
     143                 :          4 :     return NULL;
     144                 :            : }

Generated by: LCOV version 1.14