(root)/
Python-3.11.7/
Modules/
_sqlite/
microprotocols.c
       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  pysqlite_microprotocols_init(PyObject *module)
      37  {
      38      /* create adapters dictionary and put it in module namespace */
      39      pysqlite_state *state = pysqlite_get_state(module);
      40      state->psyco_adapters = PyDict_New();
      41      if (state->psyco_adapters == NULL) {
      42          return -1;
      43      }
      44  
      45      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  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      key = Py_BuildValue("(OO)", (PyObject*)type, proto);
      61      if (!key) {
      62          return -1;
      63      }
      64  
      65      rc = PyDict_SetItem(state->psyco_adapters, key, cast);
      66      Py_DECREF(key);
      67  
      68      return rc;
      69  }
      70  
      71  /* pysqlite_microprotocols_adapt - adapt an object to the built-in protocol */
      72  
      73  PyObject *
      74  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      key = Py_BuildValue("(OO)", (PyObject*)Py_TYPE(obj), proto);
      85      if (!key) {
      86          return NULL;
      87      }
      88      adapter = PyDict_GetItemWithError(state->psyco_adapters, key);
      89      Py_DECREF(key);
      90      if (adapter) {
      91          Py_INCREF(adapter);
      92          adapted = PyObject_CallOneArg(adapter, obj);
      93          Py_DECREF(adapter);
      94          return adapted;
      95      }
      96      if (PyErr_Occurred()) {
      97          return NULL;
      98      }
      99  
     100      /* try to have the protocol adapt this object */
     101      if (_PyObject_LookupAttr(proto, state->str___adapt__, &adapter) < 0) {
     102          return NULL;
     103      }
     104      if (adapter) {
     105          adapted = PyObject_CallOneArg(adapter, obj);
     106          Py_DECREF(adapter);
     107  
     108          if (adapted == Py_None) {
     109              Py_DECREF(adapted);
     110          }
     111          else if (adapted || !PyErr_ExceptionMatches(PyExc_TypeError)) {
     112              return adapted;
     113          }
     114          else {
     115              PyErr_Clear();
     116          }
     117      }
     118  
     119      /* and finally try to have the object adapt itself */
     120      if (_PyObject_LookupAttr(obj, state->str___conform__, &adapter) < 0) {
     121          return NULL;
     122      }
     123      if (adapter) {
     124          adapted = PyObject_CallOneArg(adapter, proto);
     125          Py_DECREF(adapter);
     126  
     127          if (adapted == Py_None) {
     128              Py_DECREF(adapted);
     129          }
     130          else if (adapted || !PyErr_ExceptionMatches(PyExc_TypeError)) {
     131              return adapted;
     132          }
     133          else {
     134              PyErr_Clear();
     135          }
     136      }
     137  
     138      if (alt) {
     139          return Py_NewRef(alt);
     140      }
     141      /* else set the right exception and return NULL */
     142      PyErr_SetString(state->ProgrammingError, "can't adapt");
     143      return NULL;
     144  }