Add libpq version discovery

This commit is contained in:
Oleksandr Shulgin 2015-06-01 18:05:11 +02:00
parent d66165232e
commit 4bb6f9cef2
7 changed files with 74 additions and 2 deletions

View File

@ -197,6 +197,16 @@ functionalities defined by the |DBAPI|_.
.. versionadded:: 2.2.0 .. versionadded:: 2.2.0
.. function:: libpq_version()
Query actual ``libpq`` version loaded.
This function throws `NotSupportedError` if it was compiled with
``libpq < 9.1``.
.. seealso:: libpq docs for `PQlibVersion()`__
.. __: http://www.postgresql.org/docs/current/static/libpq-misc.html#LIBPQ-PQLIBVERSION
.. _sql-adaptation-objects: .. _sql-adaptation-objects:

View File

@ -109,6 +109,12 @@ The module interface respects the standard defined in the |DBAPI|_.
by the interface. For `psycopg2` is ``pyformat``. See also by the interface. For `psycopg2` is ``pyformat``. See also
:ref:`query-parameters`. :ref:`query-parameters`.
.. data:: __libpq_version__
Integer contant containing the version of ``libpq`` this `psycopg2`
module was compiled with. If this value is ``>= 90100`` then you
may query for the actually loaded version of libpq using
`~psycopg2.extensions.libpq_version()`.
.. index:: .. index::

View File

@ -57,7 +57,7 @@ from psycopg2._psycopg import IntegrityError, InterfaceError, InternalError
from psycopg2._psycopg import NotSupportedError, OperationalError from psycopg2._psycopg import NotSupportedError, OperationalError
from psycopg2._psycopg import _connect, apilevel, threadsafety, paramstyle from psycopg2._psycopg import _connect, apilevel, threadsafety, paramstyle
from psycopg2._psycopg import __version__ from psycopg2._psycopg import __version__, __libpq_version__
from psycopg2 import tz from psycopg2 import tz

View File

@ -56,7 +56,7 @@ try:
except ImportError: 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, libpq_version
from psycopg2._psycopg import string_types, binary_types, new_type, new_array_type, register_type from psycopg2._psycopg import string_types, binary_types, new_type, new_array_type, register_type
from psycopg2._psycopg import ISQLQuote, Notify, Diagnostics, Column from psycopg2._psycopg import ISQLQuote, Notify, Diagnostics, Column

View File

@ -300,6 +300,19 @@ exit:
return rv; return rv;
} }
#define psyco_libpq_version_doc "Query actual libpq version loaded."
static PyObject*
psyco_libpq_version(PyObject *self)
{
#if PG_VERSION_HEX >= 0x090100
return PyInt_FromLong(PQlibVersion());
#else
PyErr_SetString(NotSupportedError, "version discovery is not supported in libpq < 9.1");
return NULL;
#endif
}
/* psyco_encodings_fill /* psyco_encodings_fill
Fill the module's postgresql<->python encoding table */ Fill the module's postgresql<->python encoding table */
@ -704,6 +717,8 @@ static PyMethodDef psycopgMethods[] = {
METH_VARARGS|METH_KEYWORDS, typecast_from_python_doc}, METH_VARARGS|METH_KEYWORDS, typecast_from_python_doc},
{"new_array_type", (PyCFunction)typecast_array_from_python, {"new_array_type", (PyCFunction)typecast_array_from_python,
METH_VARARGS|METH_KEYWORDS, typecast_array_from_python_doc}, METH_VARARGS|METH_KEYWORDS, typecast_array_from_python_doc},
{"libpq_version", (PyCFunction)psyco_libpq_version,
METH_NOARGS, psyco_libpq_version_doc},
{"Date", (PyCFunction)psyco_Date, {"Date", (PyCFunction)psyco_Date,
METH_VARARGS, psyco_Date_doc}, METH_VARARGS, psyco_Date_doc},
@ -899,6 +914,7 @@ INIT_MODULE(_psycopg)(void)
/* set some module's parameters */ /* set some module's parameters */
PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION); PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION);
PyModule_AddStringConstant(module, "__doc__", "psycopg PostgreSQL driver"); PyModule_AddStringConstant(module, "__doc__", "psycopg PostgreSQL driver");
PyModule_AddIntConstant(module, "__libpq_version__", PG_VERSION_NUM);
PyModule_AddObject(module, "apilevel", Text_FromUTF8(APILEVEL)); PyModule_AddObject(module, "apilevel", Text_FromUTF8(APILEVEL));
PyModule_AddObject(module, "threadsafety", PyInt_FromLong(THREADSAFETY)); PyModule_AddObject(module, "threadsafety", PyInt_FromLong(THREADSAFETY));
PyModule_AddObject(module, "paramstyle", Text_FromUTF8(PARAMSTYLE)); PyModule_AddObject(module, "paramstyle", Text_FromUTF8(PARAMSTYLE));

View File

@ -416,6 +416,9 @@ class psycopg_build_ext(build_ext):
% pgversion) % pgversion)
sys.exit(1) sys.exit(1)
define_macros.append(("PG_VERSION_NUM", "%d%02d%02d" %
(pgmajor, pgminor, pgpatch)))
define_macros.append(("PG_VERSION_HEX", "0x%02X%02X%02X" % define_macros.append(("PG_VERSION_HEX", "0x%02X%02X%02X" %
(pgmajor, pgminor, pgpatch))) (pgmajor, pgminor, pgpatch)))

View File

@ -236,6 +236,43 @@ def skip_after_postgres(*ver):
return skip_after_postgres__ return skip_after_postgres__
return skip_after_postgres_ return skip_after_postgres_
def libpq_version():
import psycopg2
v = psycopg2.__libpq_version__
if v >= 90100:
v = psycopg2.extensions.libpq_version()
return v
def skip_before_libpq(*ver):
"""Skip a test if libpq we're linked to is older than a certain version."""
ver = ver + (0,) * (3 - len(ver))
def skip_before_libpq_(f):
@wraps(f)
def skip_before_libpq__(self):
v = libpq_version()
if v < int("%d%02d%02d" % ver):
return self.skipTest("skipped because libpq %d" % v)
else:
return f(self)
return skip_before_libpq__
return skip_before_libpq_
def skip_after_libpq(*ver):
"""Skip a test if libpq we're linked to is newer than a certain version."""
ver = ver + (0,) * (3 - len(ver))
def skip_after_libpq_(f):
@wraps(f)
def skip_after_libpq__(self):
v = libpq_version()
if v >= int("%d%02d%02d" % ver):
return self.skipTest("skipped because libpq %s" % v)
else:
return f(self)
return skip_after_libpq__
return skip_after_libpq_
def skip_before_python(*ver): def skip_before_python(*ver):
"""Skip a test on Python before a certain version.""" """Skip a test on Python before a certain version."""
def skip_before_python_(f): def skip_before_python_(f):