mirror of
https://github.com/psycopg/psycopg2.git
synced 2024-11-10 19:16:34 +03:00
connect() supports generic keyword arguments passed to the dsn
This commit is contained in:
parent
4254fb8566
commit
d2b67364fd
|
@ -20,7 +20,7 @@ The module interface respects the standard defined in the |DBAPI|_.
|
|||
|
||||
Create a new database session and return a new `connection` object.
|
||||
|
||||
You can specify the connection parameters either as a string::
|
||||
The connection parameters can be specified either as a string::
|
||||
|
||||
conn = psycopg2.connect("dbname=test user=postgres password=secret")
|
||||
|
||||
|
@ -28,7 +28,7 @@ The module interface respects the standard defined in the |DBAPI|_.
|
|||
|
||||
conn = psycopg2.connect(database="test", user="postgres", password="secret")
|
||||
|
||||
The full list of available parameters is:
|
||||
The basic connection parameters are:
|
||||
|
||||
- `!dbname` -- the database name (only in dsn string)
|
||||
- `!database` -- the database name (only as keyword argument)
|
||||
|
@ -36,9 +36,15 @@ The module interface respects the standard defined in the |DBAPI|_.
|
|||
- `!password` -- password used to authenticate
|
||||
- `!host` -- database host address (defaults to UNIX socket if not provided)
|
||||
- `!port` -- connection port number (defaults to 5432 if not provided)
|
||||
- `!sslmode` -- `SSL TCP/IP negotiation`__ mode
|
||||
|
||||
.. __: http://www.postgresql.org/docs/9.0/static/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS
|
||||
Any other connection parameter supported by the client library/server can
|
||||
be passed either in the connection string or as keyword. See the
|
||||
PostgreSQL documentation for a complete `list of supported parameters`__.
|
||||
Also note that the same parameters can be passed to the client library
|
||||
using `environment variables`__.
|
||||
|
||||
.. __: http://www.postgresql.org/docs/9.1/static/libpq-connect.html#LIBPQ-PQCONNECTDBPARAMS
|
||||
.. __: http://www.postgresql.org/docs/9.1/static/libpq-envars.html
|
||||
|
||||
Using the *connection_factory* parameter a different class or
|
||||
connections factory can be specified. It should be a callable object
|
||||
|
@ -48,6 +54,10 @@ The module interface respects the standard defined in the |DBAPI|_.
|
|||
Using *async*\=1 an asynchronous connection will be created: see
|
||||
:ref:`async-support` to know about advantages and limitations.
|
||||
|
||||
.. versionchanged:: 2.4.3
|
||||
any keyword argument is passed to the connection. Previously only the
|
||||
basic parameters (plus `!sslmode`) were supported as keywords.
|
||||
|
||||
.. extension::
|
||||
|
||||
The parameters *connection_factory* and *async* are Psycopg extensions
|
||||
|
|
|
@ -73,7 +73,7 @@ from psycopg2._psycopg import Error, Warning, DataError, DatabaseError, Programm
|
|||
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 _connect, apilevel, threadsafety, paramstyle
|
||||
from psycopg2._psycopg import __version__
|
||||
|
||||
from psycopg2 import tz
|
||||
|
@ -97,5 +97,64 @@ else:
|
|||
_ext.register_adapter(Decimal, Adapter)
|
||||
del Decimal, Adapter
|
||||
|
||||
|
||||
def connect(dsn=None,
|
||||
database=None, user=None, password=None, host=None, port=None,
|
||||
connection_factory=None, async=False, **kwargs):
|
||||
"""
|
||||
Create a new database connection.
|
||||
|
||||
The connection parameters can be specified either as a string:
|
||||
|
||||
conn = psycopg2.connect("dbname=test user=postgres password=secret")
|
||||
|
||||
or using a set of keyword arguments:
|
||||
|
||||
conn = psycopg2.connect(database="test", user="postgres", password="secret")
|
||||
|
||||
The basic connection parameters are:
|
||||
|
||||
- *dbname*: the database name (only in dsn string)
|
||||
- *database*: the database name (only as keyword argument)
|
||||
- *user*: user name used to authenticate
|
||||
- *password*: password used to authenticate
|
||||
- *host*: database host address (defaults to UNIX socket if not provided)
|
||||
- *port*: connection port number (defaults to 5432 if not provided)
|
||||
|
||||
Using the *connection_factory* parameter a different class or connections
|
||||
factory can be specified. It should be a callable object taking a dsn
|
||||
argument.
|
||||
|
||||
Using *async*=True an asynchronous connection will be created.
|
||||
|
||||
Any other keyword parameter will be passed to the underlying client
|
||||
library: the list of supported parameter depends on the library version.
|
||||
|
||||
"""
|
||||
|
||||
if dsn is None:
|
||||
items = []
|
||||
if database is not None:
|
||||
items.append(('dbname', database))
|
||||
if user is not None:
|
||||
items.append(('user', user))
|
||||
if password is not None:
|
||||
items.append(('password', password))
|
||||
if host is not None:
|
||||
items.append(('host', host))
|
||||
if port is not None:
|
||||
items.append(('port', port))
|
||||
|
||||
items.extend(
|
||||
[(k, v) for (k, v) in kwargs.iteritems() if v is not None])
|
||||
dsn = " ".join(["%s=%s" % item for item in items])
|
||||
|
||||
if not dsn:
|
||||
raise InterfaceError('missing dsn and no parameters')
|
||||
|
||||
return _connect(dsn,
|
||||
connection_factory=connection_factory, async=async)
|
||||
|
||||
|
||||
__all__ = filter(lambda k: not k.startswith('_'), locals().keys())
|
||||
|
||||
|
|
|
@ -75,150 +75,30 @@ HIDDEN PyObject *psyco_DescriptionType = NULL;
|
|||
|
||||
/** connect module-level function **/
|
||||
#define psyco_connect_doc \
|
||||
"connect(dsn, ...) -- Create a new database connection.\n\n" \
|
||||
"This function supports two different but equivalent sets of arguments.\n" \
|
||||
"A single data source name or ``dsn`` string can be used to specify the\n" \
|
||||
"connection parameters, as follows::\n\n" \
|
||||
" psycopg2.connect(\"dbname=xxx user=xxx ...\")\n\n" \
|
||||
"If ``dsn`` is not provided it is possible to pass the parameters as\n" \
|
||||
"keyword arguments; e.g.::\n\n" \
|
||||
" psycopg2.connect(database='xxx', user='xxx', ...)\n\n" \
|
||||
"The full list of available parameters is:\n\n" \
|
||||
"- ``dbname`` -- database name (only in 'dsn')\n" \
|
||||
"- ``database`` -- database name (only as keyword argument)\n" \
|
||||
"- ``host`` -- host address (defaults to UNIX socket if not provided)\n" \
|
||||
"- ``port`` -- port number (defaults to 5432 if not provided)\n" \
|
||||
"- ``user`` -- user name used to authenticate\n" \
|
||||
"- ``password`` -- password used to authenticate\n" \
|
||||
"- ``sslmode`` -- SSL mode (see PostgreSQL documentation)\n\n" \
|
||||
"- ``async`` -- if the connection should provide asynchronous API\n\n" \
|
||||
"If the ``connection_factory`` keyword argument is not provided this\n" \
|
||||
"function always return an instance of the `connection` class.\n" \
|
||||
"Else the given sub-class of `extensions.connection` will be used to\n" \
|
||||
"instantiate the connection object.\n\n" \
|
||||
":return: New database connection\n" \
|
||||
":rtype: `extensions.connection`"
|
||||
|
||||
static size_t
|
||||
_psyco_connect_fill_dsn(char *dsn, const char *kw, const char *v, size_t i)
|
||||
{
|
||||
strcpy(&dsn[i], kw); i += strlen(kw);
|
||||
strcpy(&dsn[i], v); i += strlen(v);
|
||||
return i;
|
||||
}
|
||||
"_connect(dsn, [connection_factory], [async]) -- New database connection.\n\n"
|
||||
|
||||
static PyObject *
|
||||
psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
|
||||
{
|
||||
PyObject *conn = NULL, *factory = NULL;
|
||||
PyObject *pyport = NULL;
|
||||
|
||||
size_t idsn=-1;
|
||||
int iport=-1;
|
||||
const char *dsn_static = NULL;
|
||||
char *dsn_dynamic=NULL;
|
||||
const char *database=NULL, *user=NULL, *password=NULL;
|
||||
const char *host=NULL, *sslmode=NULL;
|
||||
char port[16];
|
||||
PyObject *conn = NULL;
|
||||
PyObject *factory = NULL;
|
||||
const char *dsn = NULL;
|
||||
int async = 0;
|
||||
|
||||
static char *kwlist[] = {"dsn", "database", "host", "port",
|
||||
"user", "password", "sslmode",
|
||||
"connection_factory", "async", NULL};
|
||||
static char *kwlist[] = {"dsn", "connection_factory", "async", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sssOsssOi", kwlist,
|
||||
&dsn_static, &database, &host, &pyport,
|
||||
&user, &password, &sslmode,
|
||||
&factory, &async)) {
|
||||
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|Oi", kwlist,
|
||||
&dsn, &factory, &async)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (pyport && PyString_Check(pyport)) {
|
||||
PyObject *pyint = PyInt_FromString(PyString_AsString(pyport), NULL, 10);
|
||||
if (!pyint) goto fail;
|
||||
/* Must use PyInt_AsLong rather than PyInt_AS_LONG, because
|
||||
* PyInt_FromString can return a PyLongObject: */
|
||||
iport = PyInt_AsLong(pyint);
|
||||
Py_DECREF(pyint);
|
||||
if (iport == -1 && PyErr_Occurred())
|
||||
goto fail;
|
||||
}
|
||||
else if (pyport && PyInt_Check(pyport)) {
|
||||
iport = PyInt_AsLong(pyport);
|
||||
if (iport == -1 && PyErr_Occurred())
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
if (pyport && PyUnicode_Check(pyport)) {
|
||||
PyObject *pyint = PyObject_CallFunction((PyObject*)&PyLong_Type,
|
||||
"Oi", pyport, 10);
|
||||
if (!pyint) goto fail;
|
||||
iport = PyLong_AsLong(pyint);
|
||||
Py_DECREF(pyint);
|
||||
if (iport == -1 && PyErr_Occurred())
|
||||
goto fail;
|
||||
}
|
||||
else if (pyport && PyLong_Check(pyport)) {
|
||||
iport = PyLong_AsLong(pyport);
|
||||
if (iport == -1 && PyErr_Occurred())
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
else if (pyport != NULL) {
|
||||
PyErr_SetString(PyExc_TypeError, "port must be a string or int");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (iport > 0)
|
||||
PyOS_snprintf(port, 16, "%d", iport);
|
||||
|
||||
if (dsn_static == NULL) {
|
||||
size_t l = 46; /* len(" dbname= user= password= host= port= sslmode=\0") */
|
||||
|
||||
if (database) l += strlen(database);
|
||||
if (host) l += strlen(host);
|
||||
if (iport > 0) l += strlen(port);
|
||||
if (user) l += strlen(user);
|
||||
if (password) l += strlen(password);
|
||||
if (sslmode) l += strlen(sslmode);
|
||||
|
||||
dsn_dynamic = malloc(l*sizeof(char));
|
||||
if (dsn_dynamic == NULL) {
|
||||
PyErr_SetString(InterfaceError, "dynamic dsn allocation failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
idsn = 0;
|
||||
if (database)
|
||||
idsn = _psyco_connect_fill_dsn(dsn_dynamic, " dbname=", database, idsn);
|
||||
if (host)
|
||||
idsn = _psyco_connect_fill_dsn(dsn_dynamic, " host=", host, idsn);
|
||||
if (iport > 0)
|
||||
idsn = _psyco_connect_fill_dsn(dsn_dynamic, " port=", port, idsn);
|
||||
if (user)
|
||||
idsn = _psyco_connect_fill_dsn(dsn_dynamic, " user=", user, idsn);
|
||||
if (password)
|
||||
idsn = _psyco_connect_fill_dsn(dsn_dynamic, " password=", password, idsn);
|
||||
if (sslmode)
|
||||
idsn = _psyco_connect_fill_dsn(dsn_dynamic, " sslmode=", sslmode, idsn);
|
||||
|
||||
if (idsn > 0) {
|
||||
dsn_dynamic[idsn] = '\0';
|
||||
memmove(dsn_dynamic, &dsn_dynamic[1], idsn);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(InterfaceError, "missing dsn and no parameters");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const char *dsn = (dsn_static != NULL ? dsn_static : dsn_dynamic);
|
||||
Dprintf("psyco_connect: dsn = '%s', async = %d", dsn, async);
|
||||
|
||||
/* allocate connection, fill with errors and return it */
|
||||
if (factory == NULL) factory = (PyObject *)&connectionType;
|
||||
if (factory == NULL || factory == Py_None) {
|
||||
factory = (PyObject *)&connectionType;
|
||||
}
|
||||
|
||||
/* Here we are breaking the connection.__init__ interface defined
|
||||
* by psycopg2. So, if not requiring an async conn, avoid passing
|
||||
* the async parameter. */
|
||||
|
@ -231,20 +111,6 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds)
|
|||
} else {
|
||||
conn = PyObject_CallFunction(factory, "si", dsn, async);
|
||||
}
|
||||
}
|
||||
|
||||
goto cleanup;
|
||||
fail:
|
||||
assert (PyErr_Occurred());
|
||||
if (conn != NULL) {
|
||||
Py_DECREF(conn);
|
||||
conn = NULL;
|
||||
}
|
||||
/* Fall through to cleanup: */
|
||||
cleanup:
|
||||
if (dsn_dynamic != NULL) {
|
||||
free(dsn_dynamic);
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
@ -754,7 +620,7 @@ exit:
|
|||
/** method table and module initialization **/
|
||||
|
||||
static PyMethodDef psycopgMethods[] = {
|
||||
{"connect", (PyCFunction)psyco_connect,
|
||||
{"_connect", (PyCFunction)psyco_connect,
|
||||
METH_VARARGS|METH_KEYWORDS, psyco_connect_doc},
|
||||
{"adapt", (PyCFunction)psyco_microprotocols_adapt,
|
||||
METH_VARARGS, psyco_microprotocols_adapt_doc},
|
||||
|
|
Loading…
Reference in New Issue
Block a user