diff --git a/doc/src/connection.rst b/doc/src/connection.rst index 5310458b..7b023763 100644 --- a/doc/src/connection.rst +++ b/doc/src/connection.rst @@ -740,6 +740,20 @@ The ``connection`` class Return `!True` if the connection is executing an asynchronous operation. + .. rubric:: Interoperation with other C API modules + + .. method:: get_native_connection() + + Return the internal `PGconn*` wrapped in a PyCapsule object. This is + only useful for passing the `libpq` raw connection associated to this + connection object to other C-level modules that may have a use for it. + + .. seealso:: Python C API `Capsules`__ docs. + + .. __: https://docs.python.org/3.1/c-api/capsule.html + + .. versionadded:: 2.8 + .. rubric:: informative methods of the native connection diff --git a/psycopg/connection_type.c b/psycopg/connection_type.c index a9e23fbc..71b07221 100644 --- a/psycopg/connection_type.c +++ b/psycopg/connection_type.c @@ -826,6 +826,20 @@ psyco_conn_deferrable_set(connectionObject *self, PyObject *pyvalue) } +/* psyco_get_native_connection - expose PGconn* as a Python capsule */ + +#define psyco_get_native_connection_doc \ +"_get_native_connection() -- Return the internal PGconn* as a Python Capsule." + +static PyObject * +psyco_get_native_connection(connectionObject *self) +{ + EXC_IF_CONN_CLOSED(self); + + return PyCapsule_New(self->pgconn, "psycopg2.connection.native_connection", NULL); +} + + /* set_client_encoding method - set client encoding */ #define psyco_conn_set_client_encoding_doc \ @@ -1194,6 +1208,8 @@ static struct PyMethodDef connectionObject_methods[] = { METH_NOARGS, psyco_conn_isexecuting_doc}, {"cancel", (PyCFunction)psyco_conn_cancel, METH_NOARGS, psyco_conn_cancel_doc}, + {"_get_native_connection", (PyCFunction)psyco_get_native_connection, + METH_NOARGS, psyco_get_native_connection_doc}, {NULL} }; diff --git a/tests/test_connection.py b/tests/test_connection.py index ffc9887f..d8f0ed50 100755 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -340,6 +340,11 @@ class ConnectionTests(ConnectingTestCase): self.assert_(c.closed, "connection failed so it must be closed") self.assert_('foobar' not in c.dsn, "password was not obscured") + def test_get_native_connection(self): + conn = self.connect() + capsule = conn._get_native_connection() + # we can't do anything else in Python + self.assertIsNotNone(capsule) class ParseDsnTestCase(ConnectingTestCase): def test_parse_dsn(self):