From 0285ec6beb695bf38ae5cccef8245e04fe5585a0 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 14 Aug 2007 00:40:23 +0000 Subject: [PATCH] added engine_from_config() function for helping to create_engine() from an .ini style config --- lib/sqlalchemy/__init__.py | 2 +- lib/sqlalchemy/engine/__init__.py | 28 ++++++++++++++++++++++++++++ lib/sqlalchemy/engine/url.py | 12 +++++++++++- test/engine/parseconnect.py | 30 ++++++++++++++++++++++-------- 4 files changed, 62 insertions(+), 10 deletions(-) diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py index ab12ecf4b2..bdd3604de9 100644 --- a/lib/sqlalchemy/__init__.py +++ b/lib/sqlalchemy/__init__.py @@ -7,7 +7,7 @@ from sqlalchemy.types import * from sqlalchemy.sql import * from sqlalchemy.schema import * -from sqlalchemy.engine import create_engine +from sqlalchemy.engine import create_engine, engine_from_config __version__ = 'svn' diff --git a/lib/sqlalchemy/engine/__init__.py b/lib/sqlalchemy/engine/__init__.py index 2ef163c037..acac8180ce 100644 --- a/lib/sqlalchemy/engine/__init__.py +++ b/lib/sqlalchemy/engine/__init__.py @@ -48,6 +48,7 @@ The package is represented among several individual modules, including: import sqlalchemy.databases from sqlalchemy.engine.base import * from sqlalchemy.engine import strategies +from sqlalchemy import util def engine_descriptors(): """Provide a listing of all the database implementations supported. @@ -151,3 +152,30 @@ def create_engine(*args, **kwargs): strategy = kwargs.pop('strategy', default_strategy) strategy = strategies.strategies[strategy] return strategy.create(*args, **kwargs) + +def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs): + """Create a new Engine instance using a configuration dictionary. + + the dictionary is typically produced from a config file where keys are prefixed, + such as sqlalchemy.url, sqlalchemy.echo, etc. The 'prefix' argument indicates + the prefix to be searched for. + + A select set of keyword arguments will be "coerced" to their expected type based on + string values. in a future release, this functionality will be expanded to include + dialect-specific arguments. + """ + + opts = dict([(key[len(prefix):], configuration[key]) for key in configuration if key.startswith(prefix)]) + for opt, type_ in ( + ('convert_unicode', bool), + ('pool_timeout', int), + ('echo', bool), + ('echo_pool', bool), + ('pool_recycle', int), + ): + util.coerce_kw_type(opts, opt, type_) + opts.update(kwargs) + url = opts.pop('url') + return create_engine(url, **opts) + + \ No newline at end of file diff --git a/lib/sqlalchemy/engine/url.py b/lib/sqlalchemy/engine/url.py index 98d4d442e1..31546bae8f 100644 --- a/lib/sqlalchemy/engine/url.py +++ b/lib/sqlalchemy/engine/url.py @@ -66,7 +66,17 @@ class URL(object): keys.sort() s += '?' + "&".join(["%s=%s" % (k, self.query[k]) for k in keys]) return s - + + def __eq__(self, other): + return \ + isinstance(other, URL) and \ + self.drivername == other.drivername and \ + self.username == other.username and \ + self.password == other.password and \ + self.host == other.host and \ + self.database == other.database and \ + self.query == other.query + def get_dialect(self): """Return the SQLAlchemy database dialect class corresponding to this URL's driver name.""" dialect=None diff --git a/test/engine/parseconnect.py b/test/engine/parseconnect.py index fef3742cf8..14def8d3b0 100644 --- a/test/engine/parseconnect.py +++ b/test/engine/parseconnect.py @@ -5,7 +5,7 @@ from testlib import * class ParseConnectTest(PersistTest): - def testrfc1738(self): + def test_rfc1738(self): for text in ( 'dbtype://username:password@hostspec:110//usr/db_file.db', 'dbtype://username:password@hostspec/database', @@ -37,21 +37,35 @@ class ParseConnectTest(PersistTest): class CreateEngineTest(PersistTest): """test that create_engine arguments of different types get propigated properly""" - def testconnectquery(self): + def test_connect_query(self): dbapi = MockDBAPI(foober='12', lala='18', fooz='somevalue') # start the postgres dialect, but put our mock DBAPI as the module instead of psycopg e = create_engine('postgres://scott:tiger@somehost/test?foober=12&lala=18&fooz=somevalue', module=dbapi) c = e.connect() - def testkwargs(self): + def test_kwargs(self): dbapi = MockDBAPI(foober=12, lala=18, hoho={'this':'dict'}, fooz='somevalue') # start the postgres dialect, but put our mock DBAPI as the module instead of psycopg e = create_engine('postgres://scott:tiger@somehost/test?fooz=somevalue', connect_args={'foober':12, 'lala':18, 'hoho':{'this':'dict'}}, module=dbapi) c = e.connect() - def testcustom(self): + def test_engine_from_config(self): + dbapi = MockDBAPI() + + config = { + 'sqlalchemy.url':'postgres://scott:tiger@somehost/test?fooz=somevalue', + 'sqlalchemy.echo':'1', + 'sqlalchemy.pool_recycle':50 + } + + e = engine_from_config(config, module=dbapi) + assert e.pool._recycle == 50 + assert e.echo is True + assert e.url == url.make_url('postgres://scott:tiger@somehost/test?fooz=somevalue') + + def test_custom(self): dbapi = MockDBAPI(foober=12, lala=18, hoho={'this':'dict'}, fooz='somevalue') def connect(): @@ -61,12 +75,12 @@ class CreateEngineTest(PersistTest): e = create_engine('postgres://', creator=connect, module=dbapi) c = e.connect() - def testrecycle(self): + def test_recycle(self): dbapi = MockDBAPI(foober=12, lala=18, hoho={'this':'dict'}, fooz='somevalue') e = create_engine('postgres://', pool_recycle=472, module=dbapi) assert e.pool._recycle == 472 - def testbadargs(self): + def test_badargs(self): # good arg, use MockDBAPI to prevent oracle import errors e = create_engine('oracle://', use_ansi=True, module=MockDBAPI()) @@ -124,7 +138,7 @@ class CreateEngineTest(PersistTest): except exceptions.DBAPIError: assert True - def testurlattr(self): + def test_urlattr(self): """test the url attribute on ``Engine``.""" e = create_engine('mysql://scott:tiger@localhost/test', module=MockDBAPI()) @@ -134,7 +148,7 @@ class CreateEngineTest(PersistTest): assert e.url.username == e2.url.username == 'scott' assert e2.url is u - def testpoolargs(self): + def test_poolargs(self): """test that connection pool args make it thru""" e = create_engine('postgres://', creator=None, pool_recycle=50, echo_pool=None, module=MockDBAPI()) assert e.pool._recycle == 50 -- 2.47.3