diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-04-17 20:49:35 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-04-17 20:49:35 +0000 |
| commit | aabb6e530b05bee9cc5c2382a308a987abd6168e (patch) | |
| tree | cd937947baf100d75e679e2f6d40e3a287ffc196 /lib | |
| parent | 8d7a271b8687dbcb58cac713f9e16e445d242881 (diff) | |
| download | sqlalchemy-aabb6e530b05bee9cc5c2382a308a987abd6168e.tar.gz | |
- the dialects within sqlalchemy.databases become a setuptools
entry points. loading the built-in database dialects works the
same as always, but if none found will fall back to trying
pkg_resources to load an external module [ticket:521]
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/sqlalchemy/databases/firebird.py | 8 | ||||
| -rw-r--r-- | lib/sqlalchemy/databases/mssql.py | 34 | ||||
| -rw-r--r-- | lib/sqlalchemy/databases/mysql.py | 8 | ||||
| -rw-r--r-- | lib/sqlalchemy/databases/oracle.py | 10 | ||||
| -rw-r--r-- | lib/sqlalchemy/databases/postgres.py | 20 | ||||
| -rw-r--r-- | lib/sqlalchemy/databases/sqlite.py | 28 | ||||
| -rw-r--r-- | lib/sqlalchemy/engine/strategies.py | 20 | ||||
| -rw-r--r-- | lib/sqlalchemy/engine/url.py | 25 |
8 files changed, 86 insertions, 67 deletions
diff --git a/lib/sqlalchemy/databases/firebird.py b/lib/sqlalchemy/databases/firebird.py index 2ab88101a..4695426eb 100644 --- a/lib/sqlalchemy/databases/firebird.py +++ b/lib/sqlalchemy/databases/firebird.py @@ -15,9 +15,6 @@ import sqlalchemy.ansisql as ansisql import sqlalchemy.types as sqltypes import sqlalchemy.exceptions as exceptions -def dbapi(): - import kinterbasdb - return kinterbasdb _initialized_kb = False @@ -113,6 +110,11 @@ class FBDialect(ansisql.ANSIDialect): self.type_conv = type_conv self.concurrency_level= concurrency_level + def dbapi(cls): + import kinterbasdb + return kinterbasdb + dbapi = classmethod(dbapi) + def create_connect_args(self, url): opts = url.translate_connect_args(['host', 'database', 'user', 'password', 'port']) if opts.get('port'): diff --git a/lib/sqlalchemy/databases/mssql.py b/lib/sqlalchemy/databases/mssql.py index 41b51d12d..22fafad81 100644 --- a/lib/sqlalchemy/databases/mssql.py +++ b/lib/sqlalchemy/databases/mssql.py @@ -52,21 +52,6 @@ import sqlalchemy.ansisql as ansisql import sqlalchemy.types as sqltypes import sqlalchemy.exceptions as exceptions -def dbapi(module_name=None): - if module_name: - try: - dialect_cls = dialect_mapping[module_name] - return dialect_cls.import_dbapi() - except KeyError: - raise exceptions.InvalidRequestError("Unsupported MSSQL module '%s' requested (must be adodbpi, pymssql or pyodbc)" % module_name) - else: - for dialect_cls in [MSSQLDialect_adodbapi, MSSQLDialect_pymssql, MSSQLDialect_pyodbc]: - try: - return dialect_cls.import_dbapi() - except ImportError, e: - pass - else: - raise ImportError('No DBAPI module detected for MSSQL - please install adodbapi, pymssql or pyodbc') class MSNumeric(sqltypes.Numeric): def convert_result_value(self, value, dialect): @@ -331,7 +316,24 @@ class MSSQLDialect(ansisql.ANSIDialect): self.auto_identity_insert = auto_identity_insert self.text_as_varchar = False self.set_default_schema_name("dbo") - + + def dbapi(cls, module_name=None): + if module_name: + try: + dialect_cls = dialect_mapping[module_name] + return dialect_cls.import_dbapi() + except KeyError: + raise exceptions.InvalidRequestError("Unsupported MSSQL module '%s' requested (must be adodbpi, pymssql or pyodbc)" % module_name) + else: + for dialect_cls in [MSSQLDialect_adodbapi, MSSQLDialect_pymssql, MSSQLDialect_pyodbc]: + try: + return dialect_cls.import_dbapi() + except ImportError, e: + pass + else: + raise ImportError('No DBAPI module detected for MSSQL - please install adodbapi, pymssql or pyodbc') + dbapi = classmethod(dbapi) + def create_connect_args(self, url): opts = url.translate_connect_args(['host', 'database', 'user', 'password', 'port']) opts.update(url.query) diff --git a/lib/sqlalchemy/databases/mysql.py b/lib/sqlalchemy/databases/mysql.py index d3a42ccdc..21f8bb398 100644 --- a/lib/sqlalchemy/databases/mysql.py +++ b/lib/sqlalchemy/databases/mysql.py @@ -12,9 +12,6 @@ import sqlalchemy.types as sqltypes import sqlalchemy.exceptions as exceptions from array import array -def dbapi(): - import MySQLdb as mysql - return mysql def kw_colspec(self, spec): if self.unsigned: @@ -280,6 +277,11 @@ class MySQLDialect(ansisql.ANSIDialect): def __init__(self, **kwargs): ansisql.ANSIDialect.__init__(self, default_paramstyle='format', **kwargs) + def dbapi(cls): + import MySQLdb as mysql + return mysql + dbapi = classmethod(dbapi) + def create_connect_args(self, url): opts = url.translate_connect_args(['host', 'db', 'user', 'passwd', 'port']) opts.update(url.query) diff --git a/lib/sqlalchemy/databases/oracle.py b/lib/sqlalchemy/databases/oracle.py index fce59a072..f49f1d4c0 100644 --- a/lib/sqlalchemy/databases/oracle.py +++ b/lib/sqlalchemy/databases/oracle.py @@ -11,9 +11,6 @@ from sqlalchemy import util, sql, engine, schema, ansisql, exceptions, logging from sqlalchemy.engine import default, base import sqlalchemy.types as sqltypes -def dbapi(): - import cx_Oracle - return cx_Oracle class OracleNumeric(sqltypes.Numeric): @@ -172,7 +169,12 @@ class OracleDialect(ansisql.ANSIDialect): self.ORACLE_BINARY_TYPES = [getattr(self.dbapi, k) for k in ["BFILE", "CLOB", "NCLOB", "BLOB", "LONG_BINARY", "LONG_STRING"] if hasattr(self.dbapi, k)] else: self.ORACLE_BINARY_TYPES = [] - + + def dbapi(cls): + import cx_Oracle + return cx_Oracle + dbapi = classmethod(dbapi) + def create_connect_args(self, url): if url.database: # if we have a database, then we have a remote host diff --git a/lib/sqlalchemy/databases/postgres.py b/lib/sqlalchemy/databases/postgres.py index a93ba200c..0eca18be3 100644 --- a/lib/sqlalchemy/databases/postgres.py +++ b/lib/sqlalchemy/databases/postgres.py @@ -16,15 +16,6 @@ try: except: mxDateTime = None -def dbapi(): - try: - import psycopg2 as psycopg - except ImportError, e: - try: - import psycopg - except ImportError, e2: - raise e - return psycopg class PGInet(sqltypes.TypeEngine): def get_col_spec(self): @@ -258,6 +249,17 @@ class PGDialect(ansisql.ANSIDialect): self.use_information_schema = use_information_schema self.paramstyle = 'pyformat' + def dbapi(cls): + try: + import psycopg2 as psycopg + except ImportError, e: + try: + import psycopg + except ImportError, e2: + raise e + return psycopg + dbapi = classmethod(dbapi) + def create_connect_args(self, url): opts = url.translate_connect_args(['host', 'database', 'user', 'password', 'port']) if opts.has_key('port'): diff --git a/lib/sqlalchemy/databases/sqlite.py b/lib/sqlalchemy/databases/sqlite.py index 2b7e28dfb..0222496f8 100644 --- a/lib/sqlalchemy/databases/sqlite.py +++ b/lib/sqlalchemy/databases/sqlite.py @@ -12,18 +12,6 @@ import sqlalchemy.engine.default as default import sqlalchemy.types as sqltypes import datetime,time -def dbapi(): - try: - from pysqlite2 import dbapi2 as sqlite - except ImportError, e: - try: - from sqlite3 import dbapi2 as sqlite #try the 2.5+ stdlib name. - except ImportError: - try: - sqlite = __import__('sqlite') # skip ourselves - except ImportError: - raise e - return sqlite class SLNumeric(sqltypes.Numeric): def get_col_spec(self): @@ -160,6 +148,20 @@ class SQLiteDialect(ansisql.ANSIDialect): return tuple([int(x) for x in num.split('.')]) self.supports_cast = (self.dbapi is None or vers(self.dbapi.sqlite_version) >= vers("3.2.3")) + def dbapi(cls): + try: + from pysqlite2 import dbapi2 as sqlite + except ImportError, e: + try: + from sqlite3 import dbapi2 as sqlite #try the 2.5+ stdlib name. + except ImportError: + try: + sqlite = __import__('sqlite') # skip ourselves + except ImportError: + raise e + return sqlite + dbapi = classmethod(dbapi) + def compiler(self, statement, bindparams, **kwargs): return SQLiteCompiler(self, statement, bindparams, **kwargs) @@ -347,4 +349,4 @@ class SQLiteIdentifierPreparer(ansisql.ANSIIdentifierPreparer): super(SQLiteIdentifierPreparer, self).__init__(dialect, omit_schema=True) dialect = SQLiteDialect -poolclass = pool.SingletonThreadPool +dialect.poolclass = pool.SingletonThreadPool diff --git a/lib/sqlalchemy/engine/strategies.py b/lib/sqlalchemy/engine/strategies.py index ba9b0968a..ed31743d8 100644 --- a/lib/sqlalchemy/engine/strategies.py +++ b/lib/sqlalchemy/engine/strategies.py @@ -41,27 +41,26 @@ class DefaultEngineStrategy(EngineStrategy): # create url.URL object u = url.make_url(name_or_url) - # get module from sqlalchemy.databases - module = u.get_module() + dialect_cls = u.get_dialect() dialect_args = {} # consume dialect arguments from kwargs - for k in util.get_cls_kwargs(module.dialect): + for k in util.get_cls_kwargs(dialect_cls): if k in kwargs: dialect_args[k] = kwargs.pop(k) dbapi = kwargs.pop('module', None) if dbapi is None: dbapi_args = {} - for k in util.get_func_kwargs(module.dbapi): + for k in util.get_func_kwargs(dialect_cls.dbapi): if k in kwargs: dbapi_args[k] = kwargs.pop(k) - dbapi = module.dbapi(**dbapi_args) + dbapi = dialect_cls.dbapi(**dbapi_args) dialect_args['dbapi'] = dbapi # create dialect - dialect = module.dialect(**dialect_args) + dialect = dialect_cls(**dialect_args) # assemble connection arguments (cargs, cparams) = dialect.create_connect_args(u) @@ -77,7 +76,7 @@ class DefaultEngineStrategy(EngineStrategy): raise exceptions.DBAPIError("Connection failed", e) creator = kwargs.pop('creator', connect) - poolclass = kwargs.pop('poolclass', getattr(module, 'poolclass', poollib.QueuePool)) + poolclass = kwargs.pop('poolclass', getattr(dialect_cls, 'poolclass', poollib.QueuePool)) pool_args = {} # consume pool arguments from kwargs, translating a few of the arguments @@ -158,17 +157,16 @@ class MockEngineStrategy(EngineStrategy): # create url.URL object u = url.make_url(name_or_url) - # get module from sqlalchemy.databases - module = u.get_module() + dialect_cls = u.get_dialect() dialect_args = {} # consume dialect arguments from kwargs - for k in util.get_cls_kwargs(module.dialect): + for k in util.get_cls_kwargs(dialect_cls): if k in kwargs: dialect_args[k] = kwargs.pop(k) # create dialect - dialect = module.dialect(**dialect_args) + dialect = dialect_cls(**dialect_args) return MockEngineStrategy.MockConnection(dialect, executor) diff --git a/lib/sqlalchemy/engine/url.py b/lib/sqlalchemy/engine/url.py index faa0ffc11..c5ad90ee9 100644 --- a/lib/sqlalchemy/engine/url.py +++ b/lib/sqlalchemy/engine/url.py @@ -69,19 +69,28 @@ class URL(object): s += '?' + "&".join(["%s=%s" % (k, self.query[k]) for k in keys]) return s - def get_module(self): - """Return the SQLAlchemy database module corresponding to this URL's driver name.""" + def get_dialect(self): + """Return the SQLAlchemy database dialect class corresponding to this URL's driver name.""" + dialect=None if self.drivername == 'ansi': import sqlalchemy.ansisql - return sqlalchemy.ansisql - + return sqlalchemy.ansisql.dialect + try: - return getattr(__import__('sqlalchemy.databases.%s' % self.drivername).databases, self.drivername) + module=getattr(__import__('sqlalchemy.databases.%s' % self.drivername).databases, self.drivername) + dialect=module.dialect except ImportError: if sys.exc_info()[2].tb_next is None: - raise exceptions.ArgumentError('unknown database %r' % self.drivername) - raise - + import pkg_resources + for res in pkg_resources.iter_entry_points('sqlalchemy.databases'): + if res.name==self.drivername: + dialect=res.load() + else: + raise + if dialect is not None: + return dialect + raise ImportError('unknown database %r' % self.drivername) + def translate_connect_args(self, names): """Translate this URL's attributes into a dictionary of connection arguments. |
