mirror of
				https://github.com/psycopg/psycopg2.git
				synced 2025-11-04 01:37:31 +03:00 
			
		
		
		
	Added new_array_type() function
Allows the creation of a generic array typecaster from Python.
This commit is contained in:
		
							parent
							
								
									6c8051907c
								
							
						
					
					
						commit
						e3054ac9f3
					
				
							
								
								
									
										2
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								NEWS
									
									
									
									
									
								
							| 
						 | 
					@ -1,6 +1,8 @@
 | 
				
			||||||
What's new in psycopg 2.4.3
 | 
					What's new in psycopg 2.4.3
 | 
				
			||||||
---------------------------
 | 
					---------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - Added 'new_array_type()' function for easy creation of array
 | 
				
			||||||
 | 
					    typecasters.
 | 
				
			||||||
  - Fixed segfault in case of transaction started with connection lost
 | 
					  - Fixed segfault in case of transaction started with connection lost
 | 
				
			||||||
    (and possibly other events).
 | 
					    (and possibly other events).
 | 
				
			||||||
  - Rollback connections in transaction or in error before putting them
 | 
					  - Rollback connections in transaction or in error before putting them
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -216,6 +216,9 @@ read:
 | 
				
			||||||
    >>> print type(point), point.x, point.y
 | 
					    >>> print type(point), point.x, point.y
 | 
				
			||||||
    <class 'Point'> 10.2 20.3
 | 
					    <class 'Point'> 10.2 20.3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A typecaster created by `!new_type()` can be also used with
 | 
				
			||||||
 | 
					`~psycopg2.extensions.new_array_type()` to create a typecaster converting a
 | 
				
			||||||
 | 
					PostgreSQL array into a Python list.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. index::
 | 
					.. index::
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -290,7 +290,7 @@ details.
 | 
				
			||||||
.. function:: new_type(oids, name, adapter)
 | 
					.. function:: new_type(oids, name, adapter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Create a new type caster to convert from a PostgreSQL type to a Python
 | 
					    Create a new type caster to convert from a PostgreSQL type to a Python
 | 
				
			||||||
    object.  The created object must be registered using
 | 
					    object.  The object created must be registered using
 | 
				
			||||||
    `register_type()` to be used.
 | 
					    `register_type()` to be used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :param oids: tuple of OIDs of the PostgreSQL type to convert.
 | 
					    :param oids: tuple of OIDs of the PostgreSQL type to convert.
 | 
				
			||||||
| 
						 | 
					@ -309,6 +309,23 @@ details.
 | 
				
			||||||
    See :ref:`type-casting-from-sql-to-python` for an usage example.
 | 
					    See :ref:`type-casting-from-sql-to-python` for an usage example.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. function:: new_array_type(oids, name, base_caster)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Create a new type caster to convert from a PostgreSQL array type to a list
 | 
				
			||||||
 | 
					    of Python object.  The object created must be registered using
 | 
				
			||||||
 | 
					    `register_type()` to be used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    :param oids: tuple of OIDs of the PostgreSQL type to convert. It should
 | 
				
			||||||
 | 
					        probably be the oid of the array type (e.g. the ``typarray`` field in
 | 
				
			||||||
 | 
					        the ``pg_type`` table.
 | 
				
			||||||
 | 
					    :param name: the name of the new type adapter.
 | 
				
			||||||
 | 
					    :param base_caster: a Psycopg typecaster, e.g. created using the
 | 
				
			||||||
 | 
					        `new_type()` function. The caster should be able to parse a single
 | 
				
			||||||
 | 
					        item of the desired type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .. versionadded:: 2.4.3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. function:: register_type(obj [, scope])
 | 
					.. function:: register_type(obj [, scope])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Register a type caster created using `new_type()`.
 | 
					    Register a type caster created using `new_type()`.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ except ImportError:
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from psycopg2._psycopg import adapt, adapters, encodings, connection, cursor, lobject, Xid
 | 
					from psycopg2._psycopg import adapt, adapters, encodings, connection, cursor, lobject, Xid
 | 
				
			||||||
from psycopg2._psycopg import string_types, binary_types, new_type, register_type
 | 
					from psycopg2._psycopg import string_types, binary_types, new_type, new_array_type, register_type
 | 
				
			||||||
from psycopg2._psycopg import ISQLQuote, Notify
 | 
					from psycopg2._psycopg import ISQLQuote, Notify
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from psycopg2._psycopg import QueryCanceledError, TransactionRollbackError
 | 
					from psycopg2._psycopg import QueryCanceledError, TransactionRollbackError
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -257,7 +257,7 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
 | 
				
			||||||
"  * `conn_or_curs`: A connection, cursor or None"
 | 
					"  * `conn_or_curs`: A connection, cursor or None"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define typecast_from_python_doc \
 | 
					#define typecast_from_python_doc \
 | 
				
			||||||
"new_type(oids, name, adapter) -> new type object\n\n" \
 | 
					"new_type(oids, name, castobj) -> new type object\n\n" \
 | 
				
			||||||
"Create a new binding object. The object can be used with the\n" \
 | 
					"Create a new binding object. The object can be used with the\n" \
 | 
				
			||||||
"`register_type()` function to bind PostgreSQL objects to python objects.\n\n" \
 | 
					"`register_type()` function to bind PostgreSQL objects to python objects.\n\n" \
 | 
				
			||||||
":Parameters:\n" \
 | 
					":Parameters:\n" \
 | 
				
			||||||
| 
						 | 
					@ -268,6 +268,15 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
 | 
				
			||||||
"    the string representation returned by PostgreSQL (`!None` if ``NULL``)\n" \
 | 
					"    the string representation returned by PostgreSQL (`!None` if ``NULL``)\n" \
 | 
				
			||||||
"    and ``cur`` is the cursor from which data are read."
 | 
					"    and ``cur`` is the cursor from which data are read."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define typecast_array_from_python_doc \
 | 
				
			||||||
 | 
					"new_array_type(oids, name, baseobj) -> new type object\n\n" \
 | 
				
			||||||
 | 
					"Create a new binding object to parse an array.\n\n" \
 | 
				
			||||||
 | 
					"The object can be used with `register_type()`.\n\n" \
 | 
				
			||||||
 | 
					":Parameters:\n" \
 | 
				
			||||||
 | 
					"  * `oids`: Tuple of ``oid`` of the PostgreSQL types to convert.\n" \
 | 
				
			||||||
 | 
					"  * `name`: Name for the new type\n" \
 | 
				
			||||||
 | 
					"  * `baseobj`: Adapter to perform type conversion of a single array item."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
_psyco_register_type_set(PyObject **dict, PyObject *type)
 | 
					_psyco_register_type_set(PyObject **dict, PyObject *type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -758,6 +767,8 @@ static PyMethodDef psycopgMethods[] = {
 | 
				
			||||||
     METH_VARARGS, psyco_register_type_doc},
 | 
					     METH_VARARGS, psyco_register_type_doc},
 | 
				
			||||||
    {"new_type", (PyCFunction)typecast_from_python,
 | 
					    {"new_type", (PyCFunction)typecast_from_python,
 | 
				
			||||||
     METH_VARARGS|METH_KEYWORDS, typecast_from_python_doc},
 | 
					     METH_VARARGS|METH_KEYWORDS, typecast_from_python_doc},
 | 
				
			||||||
 | 
					    {"new_array_type", (PyCFunction)typecast_array_from_python,
 | 
				
			||||||
 | 
					     METH_VARARGS|METH_KEYWORDS, typecast_array_from_python_doc},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {"AsIs",  (PyCFunction)psyco_AsIs,
 | 
					    {"AsIs",  (PyCFunction)psyco_AsIs,
 | 
				
			||||||
     METH_VARARGS, psyco_AsIs_doc},
 | 
					     METH_VARARGS, psyco_AsIs_doc},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -603,6 +603,29 @@ typecast_from_python(PyObject *self, PyObject *args, PyObject *keywds)
 | 
				
			||||||
    return typecast_new(name, v, cast, base);
 | 
					    return typecast_new(name, v, cast, base);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PyObject *
 | 
				
			||||||
 | 
					typecast_array_from_python(PyObject *self, PyObject *args, PyObject *keywds)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    PyObject *values, *name = NULL, *base = NULL;
 | 
				
			||||||
 | 
					    typecastObject *obj = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static char *kwlist[] = {"values", "name", "baseobj", NULL};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!O!O!", kwlist,
 | 
				
			||||||
 | 
					                                     &PyTuple_Type, &values,
 | 
				
			||||||
 | 
					                                     &Text_Type, &name,
 | 
				
			||||||
 | 
					                                     &typecastType, &base)) {
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((obj = (typecastObject *)typecast_new(name, values, NULL, base))) {
 | 
				
			||||||
 | 
					        obj->ccast = typecast_GENERIC_ARRAY_cast;
 | 
				
			||||||
 | 
					        obj->pcast = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (PyObject *)obj;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PyObject *
 | 
					PyObject *
 | 
				
			||||||
typecast_from_c(typecastObject_initlist *type, PyObject *dict)
 | 
					typecast_from_c(typecastObject_initlist *type, PyObject *dict)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,9 +77,11 @@ HIDDEN int typecast_add(PyObject *obj, PyObject *dict, int binary);
 | 
				
			||||||
/* the C callable typecastObject creator function */
 | 
					/* the C callable typecastObject creator function */
 | 
				
			||||||
HIDDEN PyObject *typecast_from_c(typecastObject_initlist *type, PyObject *d);
 | 
					HIDDEN PyObject *typecast_from_c(typecastObject_initlist *type, PyObject *d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* the python callable typecast creator function */
 | 
					/* the python callable typecast creator functions */
 | 
				
			||||||
HIDDEN PyObject *typecast_from_python(
 | 
					HIDDEN PyObject *typecast_from_python(
 | 
				
			||||||
    PyObject *self, PyObject *args, PyObject *keywds);
 | 
					    PyObject *self, PyObject *args, PyObject *keywds);
 | 
				
			||||||
 | 
					HIDDEN PyObject *typecast_array_from_python(
 | 
				
			||||||
 | 
					    PyObject *self, PyObject *args, PyObject *keywds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* the function used to dispatch typecasting calls */
 | 
					/* the function used to dispatch typecasting calls */
 | 
				
			||||||
HIDDEN PyObject *typecast_cast(
 | 
					HIDDEN PyObject *typecast_cast(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -285,6 +285,19 @@ class TypesBasicTests(unittest.TestCase):
 | 
				
			||||||
        l1 = self.execute("select -%s;", (-1L,))
 | 
					        l1 = self.execute("select -%s;", (-1L,))
 | 
				
			||||||
        self.assertEqual(1, l1)
 | 
					        self.assertEqual(1, l1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def testGenericArray(self):
 | 
				
			||||||
 | 
					        def caster(s, cur):
 | 
				
			||||||
 | 
					            if s is None: return "nada"
 | 
				
			||||||
 | 
					            return int(s) * 2
 | 
				
			||||||
 | 
					        base = psycopg2.extensions.new_type((23,), "INT4", caster)
 | 
				
			||||||
 | 
					        array = psycopg2.extensions.new_array_type((1007,), "INT4ARRAY", base)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        psycopg2.extensions.register_type(array, self.conn)
 | 
				
			||||||
 | 
					        a = self.execute("select '{1,2,3}'::int4[]")
 | 
				
			||||||
 | 
					        self.assertEqual(a, [2,4,6])
 | 
				
			||||||
 | 
					        a = self.execute("select '{1,2,NULL}'::int4[]")
 | 
				
			||||||
 | 
					        self.assertEqual(a, [2,4,'nada'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AdaptSubclassTest(unittest.TestCase):
 | 
					class AdaptSubclassTest(unittest.TestCase):
 | 
				
			||||||
    def test_adapt_subtype(self):
 | 
					    def test_adapt_subtype(self):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user