Merge branch 'master' into feature/parse-dsn

Conflicts:
	lib/extensions.py
This commit is contained in:
Oleksandr Shulgin 2015-06-02 12:42:03 +02:00
commit cc08e14162
13 changed files with 103 additions and 11 deletions

11
NEWS
View File

@ -1,6 +1,17 @@
Current release
---------------
What's new in psycopg 2.7
-------------------------
New features:
- Added `~psycopg2.__libpq_version__` and
`~psycopg2.extensions.libpq_version()` to inspect the version of the
``libpq`` library the module was compiled/loaded with
(:tickets:`#35, #323`).
What's new in psycopg 2.6.1
^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -208,6 +208,18 @@ functionalities defined by the |DBAPI|_.
.. versionadded:: 2.2.0
.. function:: libpq_version()
Return the version number of the ``libpq`` dynamic library loaded as an
integer, in the same format of `~connection.server_version`.
Raise `~psycopg2.NotSupportedError` if the ``psycopg2`` module was
compiled with a ``libpq`` version lesser than 9.1 (which can be detected
by the `~psycopg2.__libpq_version__` constant).
.. seealso:: libpq docs for `PQlibVersion()`__.
.. __: http://www.postgresql.org/docs/current/static/libpq-misc.html#LIBPQ-PQLIBVERSION
.. _sql-adaptation-objects:

View File

@ -109,6 +109,13 @@ The module interface respects the standard defined in the |DBAPI|_.
by the interface. For `psycopg2` is ``pyformat``. See also
:ref:`query-parameters`.
.. data:: __libpq_version__
Integer constant reporting the version of the ``libpq`` library this
``psycopg2`` module was compiled with (in the same format of
`~connection.server_version`). If this value is lesser than ``90100``
then you may query the version of the actually loaded library using the
`~psycopg2.extensions.libpq_version()` function.
.. index::

View File

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

View File

@ -56,7 +56,7 @@ try:
except ImportError:
pass
from psycopg2._psycopg import adapt, adapters, encodings, connection, cursor, lobject, Xid, parse_dsn
from psycopg2._psycopg import adapt, adapters, encodings, connection, cursor, lobject, Xid, libpq_version, parse_dsn
from psycopg2._psycopg import string_types, binary_types, new_type, new_array_type, register_type
from psycopg2._psycopg import ISQLQuote, Notify, Diagnostics, Column

View File

@ -39,7 +39,7 @@ static unsigned char *
binary_escape(unsigned char *from, size_t from_length,
size_t *to_length, PGconn *conn)
{
#if PG_VERSION_HEX >= 0x080104
#if PG_VERSION_NUM >= 80104
if (conn)
return PQescapeByteaConn(conn, from, from_length, to_length);
else

View File

@ -474,7 +474,7 @@ lobject_export(lobjectObject *self, const char *filename)
return retvalue;
}
#if PG_VERSION_HEX >= 0x080300
#if PG_VERSION_NUM >= 80300
RAISES_NEG int
lobject_truncate(lobjectObject *self, size_t len)
@ -511,4 +511,4 @@ lobject_truncate(lobjectObject *self, size_t len)
}
#endif /* PG_VERSION_HEX >= 0x080300 */
#endif /* PG_VERSION_NUM >= 80300 */

View File

@ -266,7 +266,7 @@ psyco_lobj_get_closed(lobjectObject *self, void *closure)
return closed;
}
#if PG_VERSION_HEX >= 0x080300
#if PG_VERSION_NUM >= 80300
#define psyco_lobj_truncate_doc \
"truncate(len=0) -- Truncate large object to given size."
@ -327,10 +327,10 @@ static struct PyMethodDef lobjectObject_methods[] = {
METH_NOARGS, psyco_lobj_unlink_doc},
{"export",(PyCFunction)psyco_lobj_export,
METH_VARARGS, psyco_lobj_export_doc},
#if PG_VERSION_HEX >= 0x080300
#if PG_VERSION_NUM >= 80300
{"truncate",(PyCFunction)psyco_lobj_truncate,
METH_VARARGS, psyco_lobj_truncate_doc},
#endif /* PG_VERSION_HEX >= 0x080300 */
#endif /* PG_VERSION_NUM >= 80300 */
{NULL}
};

View File

@ -235,7 +235,7 @@ psyco_libcrypto_threads_init(void)
if (PyImport_ImportModule("ssl") != NULL) {
/* disable libcrypto setup in libpq, so it won't stomp on the callbacks
that have already been set up */
#if PG_VERSION_HEX >= 0x080400
#if PG_VERSION_NUM >= 80400
PQinitOpenSSL(1, 0);
#endif
}
@ -350,6 +350,19 @@ exit:
return rv;
}
#define psyco_libpq_version_doc "Query actual libpq version loaded."
static PyObject*
psyco_libpq_version(PyObject *self)
{
#if PG_VERSION_NUM >= 90100
return PyInt_FromLong(PQlibVersion());
#else
PyErr_SetString(NotSupportedError, "version discovery is not supported in libpq < 9.1");
return NULL;
#endif
}
/* psyco_encodings_fill
Fill the module's postgresql<->python encoding table */
@ -756,6 +769,8 @@ static PyMethodDef psycopgMethods[] = {
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},
{"libpq_version", (PyCFunction)psyco_libpq_version,
METH_NOARGS, psyco_libpq_version_doc},
{"Date", (PyCFunction)psyco_Date,
METH_VARARGS, psyco_Date_doc},
@ -951,6 +966,7 @@ INIT_MODULE(_psycopg)(void)
/* set some module's parameters */
PyModule_AddStringConstant(module, "__version__", PSYCOPG_VERSION);
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, "threadsafety", PyInt_FromLong(THREADSAFETY));
PyModule_AddObject(module, "paramstyle", Text_FromUTF8(PARAMSTYLE));

View File

@ -62,7 +62,7 @@ psycopg_escape_string(connectionObject *conn, const char *from, Py_ssize_t len,
}
{
#if PG_VERSION_HEX >= 0x080104
#if PG_VERSION_NUM >= 80104
int err;
if (conn && conn->pgconn)
ql = PQescapeStringConn(conn->pgconn, to+eq+1, from, len, &err);

View File

@ -416,7 +416,7 @@ class psycopg_build_ext(build_ext):
% pgversion)
sys.exit(1)
define_macros.append(("PG_VERSION_HEX", "0x%02X%02X%02X" %
define_macros.append(("PG_VERSION_NUM", "%d%02d%02d" %
(pgmajor, pgminor, pgpatch)))
# enable lo64 if libpq >= 9.3 and Python 64 bits

View File

@ -320,6 +320,15 @@ import _psycopg
self.assertEqual(0, proc.returncode)
class TestVersionDiscovery(unittest.TestCase):
def test_libpq_version(self):
self.assertTrue(type(psycopg2.__libpq_version__) is int)
try:
self.assertTrue(type(psycopg2.extensions.libpq_version()) is int)
except NotSupportedError:
self.assertTrue(psycopg2.__libpq_version__ < 90100)
def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__)

View File

@ -236,6 +236,43 @@ def skip_after_postgres(*ver):
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):
"""Skip a test on Python before a certain version."""
def skip_before_python_(f):