From: Julian Mehnle Date: Thu, 21 Mar 2019 16:56:27 +0000 (+0000) Subject: postgresql.psycopg2 dialect: Correctly handle complete absence of connection parameters. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8a05c96944a0523b06e9772cfe1832e500a43641;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git postgresql.psycopg2 dialect: Correctly handle complete absence of connection parameters. psycopg2/libpq will read connection parameters from environment variables, provided an empty (not-None) connection string is passed. Fixes: #4562 --- diff --git a/doc/build/core/engines.rst b/doc/build/core/engines.rst index a22b7f22b3..e67ae3e10b 100644 --- a/doc/build/core/engines.rst +++ b/doc/build/core/engines.rst @@ -102,6 +102,15 @@ also available as a pure-Python substitute:: # pg8000 engine = create_engine('postgresql+pg8000://scott:tiger@localhost/mydatabase') +With the psycopg2 DBAPI, you can omit any connection parameters that are defined as +`PG... environment variables `_. +If *all* your connection parameters are defined as environment variables, you can +specify an empty URL:: + + engine = create_engine('postgresql://') + +Again, this works only with the psycopg2 DBAPI. + More notes on connecting to PostgreSQL at :ref:`postgresql_toplevel`. MySQL diff --git a/lib/sqlalchemy/dialects/postgresql/psycopg2.py b/lib/sqlalchemy/dialects/postgresql/psycopg2.py index 8a15a85593..bba353235b 100644 --- a/lib/sqlalchemy/dialects/postgresql/psycopg2.py +++ b/lib/sqlalchemy/dialects/postgresql/psycopg2.py @@ -85,6 +85,17 @@ using ``host`` as an additional keyword argument:: .. _psycopg2_execution_options: +Environment Connection Parameters +---------------------------------- + +psycopg2, via its underlying ``libpq`` client library, allows any connection +parameters to be omitted that are defined as `PG... environment variables +`_. If *all* your +required connection parameters are defined as environment variables, you can +specify an empty URL:: + + create_engine("postgresql+psycopg2://") + Per-Statement/Connection Execution Options ------------------------------------------- @@ -735,10 +746,13 @@ class PGDialect_psycopg2(PGDialect): def create_connect_args(self, url): opts = url.translate_connect_args(username="user") - if "port" in opts: - opts["port"] = int(opts["port"]) - opts.update(url.query) - return ([], opts) + if opts: + if "port" in opts: + opts["port"] = int(opts["port"]) + opts.update(url.query) + return ([], opts) + else: + return ([''], opts) def is_disconnect(self, e, connection, cursor): if isinstance(e, self.dbapi.Error): diff --git a/test/dialect/postgresql/test_dialect.py b/test/dialect/postgresql/test_dialect.py index cadcbdc1c0..b55c78adff 100644 --- a/test/dialect/postgresql/test_dialect.py +++ b/test/dialect/postgresql/test_dialect.py @@ -27,6 +27,7 @@ from sqlalchemy import testing from sqlalchemy import text from sqlalchemy import TypeDecorator from sqlalchemy.dialects.postgresql import base as postgresql +from sqlalchemy.dialects.postgresql import psycopg2 as psycopg2_dialect from sqlalchemy.engine import engine_from_config from sqlalchemy.engine import url from sqlalchemy.testing import engines @@ -114,6 +115,20 @@ class DialectTest(fixtures.TestBase): e = engine_from_config(config, _initialize=False) eq_(e.dialect.use_native_unicode, True) + def test_psycopg2_empty_connection_string(self): + dialect = psycopg2_dialect.dialect() + u = url.make_url("postgresql://") + cargs, cparams = dialect.create_connect_args(u) + assert cargs == [''] + assert cparams == {} + + def test_psycopg2_nonempty_connection_string(self): + dialect = psycopg2_dialect.dialect() + u = url.make_url("postgresql://host") + cargs, cparams = dialect.create_connect_args(u) + assert cargs == [] + assert cparams == {"host": "host"} + class BatchInsertsTest(fixtures.TablesTest): __only_on__ = "postgresql+psycopg2"