diff options
Diffstat (limited to 'test/lib/requires.py')
| -rw-r--r-- | test/lib/requires.py | 899 |
1 files changed, 471 insertions, 428 deletions
diff --git a/test/lib/requires.py b/test/lib/requires.py index 923dfb80d..1fff3d7c2 100644 --- a/test/lib/requires.py +++ b/test/lib/requires.py @@ -5,7 +5,7 @@ target database. """ -from exclusions import \ +from .exclusions import \ skip, \ skip_if,\ only_if,\ @@ -13,7 +13,8 @@ from exclusions import \ fails_on,\ fails_on_everything_except,\ fails_if,\ - SpecPredicate + SpecPredicate,\ + against def no_support(db, reason): return SpecPredicate(db, description=reason) @@ -22,442 +23,484 @@ def exclude(db, op, spec, description=None): return SpecPredicate(db, op, spec, description=description) from sqlalchemy import util -from test.lib import config -import testing +from ..bootstrap import config import sys crashes = skip +def _chain_decorators_on(*decorators): + def decorate(fn): + for decorator in reversed(decorators): + fn = decorator(fn) + return fn + return decorate -def _chain_decorators_on(fn, *decorators): - for decorator in reversed(decorators): - fn = decorator(fn) - return fn - -def deferrable_or_no_constraints(fn): - """Target database must support derferable constraints.""" - - return skip_if([ - no_support('firebird', 'not supported by database'), - no_support('mysql', 'not supported by database'), - no_support('mssql', 'not supported by database'), - ])(fn) - -def foreign_keys(fn): - """Target database must support foreign keys.""" - - return skip_if( - no_support('sqlite', 'not supported by database') - )(fn) - - -def unbounded_varchar(fn): - """Target database must support VARCHAR with no length""" - - return skip_if([ - "firebird", "oracle", "mysql" - ], "not supported by database" - )(fn) - -def boolean_col_expressions(fn): - """Target database must support boolean expressions as columns""" - return skip_if([ - no_support('firebird', 'not supported by database'), - no_support('oracle', 'not supported by database'), - no_support('mssql', 'not supported by database'), - no_support('sybase', 'not supported by database'), - no_support('maxdb', 'FIXME: verify not supported by database'), - no_support('informix', 'not supported by database'), - ])(fn) - -def standalone_binds(fn): - """target database/driver supports bound parameters as column expressions - without being in the context of a typed column. - - """ - return skip_if(["firebird", "mssql+mxodbc"], - "not supported by driver")(fn) - -def identity(fn): - """Target database must support GENERATED AS IDENTITY or a facsimile. - - Includes GENERATED AS IDENTITY, AUTOINCREMENT, AUTO_INCREMENT, or other - column DDL feature that fills in a DB-generated identifier at INSERT-time - without requiring pre-execution of a SEQUENCE or other artifact. - - """ - return skip_if(["firebird", "oracle", "postgresql", "sybase"], - "not supported by database" - )(fn) - -def reflectable_autoincrement(fn): - """Target database must support tables that can automatically generate - PKs assuming they were reflected. - - this is essentially all the DBs in "identity" plus Postgresql, which - has SERIAL support. FB and Oracle (and sybase?) require the Sequence to - be explicitly added, including if the table was reflected. - """ - return skip_if(["firebird", "oracle", "sybase"], - "not supported by database" - )(fn) - -def binary_comparisons(fn): - """target database/driver can allow BLOB/BINARY fields to be compared - against a bound parameter value. - """ - return skip_if(["oracle", "mssql"], - "not supported by database/driver" - )(fn) - -def independent_cursors(fn): - """Target must support simultaneous, independent database cursors - on a single connection.""" - - return skip_if(["mssql+pyodbc", "mssql+mxodbc"], "no driver support") - -def independent_connections(fn): - """Target must support simultaneous, independent database connections.""" - - # This is also true of some configurations of UnixODBC and probably win32 - # ODBC as well. - return skip_if([ - no_support("sqlite", - "independent connections disabled " - "when :memory: connections are used"), - exclude("mssql", "<", (9, 0, 0), - "SQL Server 2005+ is required for " - "independent connections" - ) - ] - )(fn) - -def updateable_autoincrement_pks(fn): - """Target must support UPDATE on autoincrement/integer primary key.""" - - return skip_if(["mssql", "sybase"], - "IDENTITY columns can't be updated")(fn) - -def isolation_level(fn): - return _chain_decorators_on( - fn, - only_on(('postgresql', 'sqlite', 'mysql'), - "DBAPI has no isolation level support"), - fails_on('postgresql+pypostgresql', - 'pypostgresql bombs on multiple isolation level calls') - ) - -def row_triggers(fn): - """Target must support standard statement-running EACH ROW triggers.""" - - return skip_if([ - # no access to same table - no_support('mysql', 'requires SUPER priv'), - exclude('mysql', '<', (5, 0, 10), 'not supported by database'), - - # huh? TODO: implement triggers for PG tests, remove this - no_support('postgresql', - 'PG triggers need to be implemented for tests'), - ])(fn) - -def correlated_outer_joins(fn): - """Target must support an outer join to a subquery which - correlates to the parent.""" - - return skip_if("oracle", 'Raises "ORA-01799: a column may not be ' - 'outer-joined to a subquery"')(fn) - -def update_from(fn): - """Target must support UPDATE..FROM syntax""" - - return only_on(['postgresql', 'mssql', 'mysql'], - "Backend does not support UPDATE..FROM")(fn) - - -def savepoints(fn): - """Target database must support savepoints.""" - - return skip_if([ - "access", - "sqlite", - "sybase", - ("mysql", "<", (5, 0, 3)), - ("informix", "<", (11, 55, "xC3")) - ], "savepoints not supported")(fn) - -def denormalized_names(fn): - """Target database must have 'denormalized', i.e. - UPPERCASE as case insensitive names.""" - - return skip_if( - lambda: not testing.db.dialect.requires_name_normalize, - "Backend does not require denormalized names." - )(fn) - -def schemas(fn): - """Target database must support external schemas, and have one - named 'test_schema'.""" - - return skip_if([ - "sqlte", - "firebird" - ], "no schema support") - -def sequences(fn): - """Target database must support SEQUENCEs.""" - - return only_if([ - "postgresql", "firebird", "oracle" - ], "no SEQUENCE support")(fn) - -def update_nowait(fn): - """Target database must support SELECT...FOR UPDATE NOWAIT""" - return skip_if(["access", "firebird", "mssql", "mysql", "sqlite", "sybase"], - "no FOR UPDATE NOWAIT support" - )(fn) - -def subqueries(fn): - """Target database must support subqueries.""" - - return skip_if(exclude('mysql', '<', (4, 1, 1)), 'no subquery support')(fn) - -def intersect(fn): - """Target database must support INTERSECT or equivalent.""" - - return fails_if([ - "firebird", "mysql", "sybase", "informix" - ], 'no support for INTERSECT')(fn) - -def except_(fn): - """Target database must support EXCEPT or equivalent (i.e. MINUS).""" - return fails_if([ - "firebird", "mysql", "sybase", "informix" - ], 'no support for EXCEPT')(fn) - -def offset(fn): - """Target database must support some method of adding OFFSET or - equivalent to a result set.""" - return fails_if([ - "sybase" - ], 'no support for OFFSET or equivalent')(fn) - -def window_functions(fn): - return only_if([ - "postgresql", "mssql", "oracle" - ], "Backend does not support window functions")(fn) - -def returning(fn): - return only_if(["postgresql", "mssql", "oracle", "firebird"], - "'returning' not supported by database" - )(fn) - -def two_phase_transactions(fn): - """Target database must support two-phase transactions.""" - - return skip_if([ - no_support('access', 'two-phase xact not supported by database'), - no_support('firebird', 'no SA implementation'), - no_support('maxdb', 'two-phase xact not supported by database'), - no_support('mssql', 'two-phase xact not supported by drivers'), - no_support('oracle', 'two-phase xact not implemented in SQLA/oracle'), - no_support('drizzle', 'two-phase xact not supported by database'), - no_support('sqlite', 'two-phase xact not supported by database'), - no_support('sybase', 'two-phase xact not supported by drivers/SQLA'), - no_support('postgresql+zxjdbc', - 'FIXME: JDBC driver confuses the transaction state, may ' - 'need separate XA implementation'), - exclude('mysql', '<', (5, 0, 3), - 'two-phase xact not supported by database'), - ])(fn) - -def views(fn): - """Target database must support VIEWs.""" - - return skip_if("drizzle", "no VIEW support")(fn) - -def unicode_connections(fn): - """Target driver must support some encoding of Unicode across the wire.""" - # TODO: expand to exclude MySQLdb versions w/ broken unicode - return skip_if([ - exclude('mysql', '<', (4, 1, 1), 'no unicode connection support'), - ])(fn) - -def unicode_ddl(fn): - """Target driver must support some encoding of Unicode across the wire.""" - # TODO: expand to exclude MySQLdb versions w/ broken unicode - return skip_if([ - no_support('maxdb', 'database support flakey'), - no_support('oracle', 'FIXME: no support in database?'), - no_support('sybase', 'FIXME: guessing, needs confirmation'), - no_support('mssql+pymssql', 'no FreeTDS support'), - exclude('mysql', '<', (4, 1, 1), 'no unicode connection support'), - ])(fn) - -def sane_rowcount(fn): - return skip_if( - lambda: not testing.db.dialect.supports_sane_rowcount, - "driver doesn't support 'sane' rowcount" - )(fn) - -def cextensions(fn): - return skip_if( - lambda: not _has_cextensions(), "C extensions not installed" - )(fn) - - -def emulated_lastrowid(fn): - """"target dialect retrieves cursor.lastrowid or an equivalent - after an insert() construct executes. - """ - return fails_on_everything_except('mysql+mysqldb', 'mysql+oursql', - 'sqlite+pysqlite', 'mysql+pymysql', - 'mssql+pyodbc', 'mssql+mxodbc')(fn) - -def dbapi_lastrowid(fn): - """"target backend includes a 'lastrowid' accessor on the DBAPI - cursor object. - - """ - return fails_on_everything_except('mysql+mysqldb', 'mysql+oursql', - 'sqlite+pysqlite', 'mysql+pymysql')(fn) - -def sane_multi_rowcount(fn): - return skip_if( - lambda: not testing.db.dialect.supports_sane_multi_rowcount, - "driver doesn't support 'sane' multi row count" +class Requirements(object): + def __init__(self, db, config): + self.db = db + self.config = config + + +class DefaultRequirements(Requirements): + @property + def deferrable_or_no_constraints(self): + """Target database must support derferable constraints.""" + + return skip_if([ + no_support('firebird', 'not supported by database'), + no_support('mysql', 'not supported by database'), + no_support('mssql', 'not supported by database'), + ]) + + @property + def foreign_keys(self): + """Target database must support foreign keys.""" + + return skip_if( + no_support('sqlite', 'not supported by database') + ) + + + @property + def unbounded_varchar(self): + """Target database must support VARCHAR with no length""" + + return skip_if([ + "firebird", "oracle", "mysql" + ], "not supported by database" + ) + + @property + def boolean_col_expressions(self): + """Target database must support boolean expressions as columns""" + return skip_if([ + no_support('firebird', 'not supported by database'), + no_support('oracle', 'not supported by database'), + no_support('mssql', 'not supported by database'), + no_support('sybase', 'not supported by database'), + no_support('maxdb', 'FIXME: verify not supported by database'), + no_support('informix', 'not supported by database'), + ]) + + @property + def standalone_binds(self): + """target database/driver supports bound parameters as column expressions + without being in the context of a typed column. + + """ + return skip_if(["firebird", "mssql+mxodbc"], + "not supported by driver") + + @property + def identity(self): + """Target database must support GENERATED AS IDENTITY or a facsimile. + + Includes GENERATED AS IDENTITY, AUTOINCREMENT, AUTO_INCREMENT, or other + column DDL feature that fills in a DB-generated identifier at INSERT-time + without requiring pre-execution of a SEQUENCE or other artifact. + + """ + return skip_if(["firebird", "oracle", "postgresql", "sybase"], + "not supported by database" + ) + + @property + def reflectable_autoincrement(self): + """Target database must support tables that can automatically generate + PKs assuming they were reflected. + + this is essentially all the DBs in "identity" plus Postgresql, which + has SERIAL support. FB and Oracle (and sybase?) require the Sequence to + be explicitly added, including if the table was reflected. + """ + return skip_if(["firebird", "oracle", "sybase"], + "not supported by database" + ) + + @property + def binary_comparisons(self): + """target database/driver can allow BLOB/BINARY fields to be compared + against a bound parameter value. + """ + return skip_if(["oracle", "mssql"], + "not supported by database/driver" + ) + + @property + def independent_cursors(self): + """Target must support simultaneous, independent database cursors + on a single connection.""" + + return skip_if(["mssql+pyodbc", "mssql+mxodbc"], "no driver support") + + @property + def independent_connections(self): + """Target must support simultaneous, independent database connections.""" + + # This is also true of some configurations of UnixODBC and probably win32 + # ODBC as well. + return skip_if([ + no_support("sqlite", + "independent connections disabled " + "when :memory: connections are used"), + exclude("mssql", "<", (9, 0, 0), + "SQL Server 2005+ is required for " + "independent connections" + ) + ] + ) + + @property + def updateable_autoincrement_pks(self): + """Target must support UPDATE on autoincrement/integer primary key.""" + + return skip_if(["mssql", "sybase"], + "IDENTITY columns can't be updated") + + @property + def isolation_level(self): + return _chain_decorators_on( + only_on(('postgresql', 'sqlite', 'mysql'), + "DBAPI has no isolation level support"), + fails_on('postgresql+pypostgresql', + 'pypostgresql bombs on multiple isolation level calls') + ) + + @property + def row_triggers(self): + """Target must support standard statement-running EACH ROW triggers.""" + + return skip_if([ + # no access to same table + no_support('mysql', 'requires SUPER priv'), + exclude('mysql', '<', (5, 0, 10), 'not supported by database'), + + # huh? TODO: implement triggers for PG tests, remove this + no_support('postgresql', + 'PG triggers need to be implemented for tests'), + ]) + + @property + def correlated_outer_joins(self): + """Target must support an outer join to a subquery which + correlates to the parent.""" + + return skip_if("oracle", 'Raises "ORA-01799: a column may not be ' + 'outer-joined to a subquery"') + + @property + def update_from(self): + """Target must support UPDATE..FROM syntax""" + + return only_on(['postgresql', 'mssql', 'mysql'], + "Backend does not support UPDATE..FROM") + + + @property + def savepoints(self): + """Target database must support savepoints.""" + + return skip_if([ + "access", + "sqlite", + "sybase", + ("mysql", "<", (5, 0, 3)), + ("informix", "<", (11, 55, "xC3")) + ], "savepoints not supported") + + @property + def denormalized_names(self): + """Target database must have 'denormalized', i.e. + UPPERCASE as case insensitive names.""" + + return skip_if( + lambda: not self.db.dialect.requires_name_normalize, + "Backend does not require denormalized names." + ) + + @property + def schemas(self): + """Target database must support external schemas, and have one + named 'test_schema'.""" + + return skip_if([ + "sqlite", + "firebird" + ], "no schema support") + + @property + def sequences(self): + """Target database must support SEQUENCEs.""" + + return only_if([ + "postgresql", "firebird", "oracle" + ], "no SEQUENCE support") + + @property + def update_nowait(self): + """Target database must support SELECT...FOR UPDATE NOWAIT""" + return skip_if(["access", "firebird", "mssql", "mysql", "sqlite", "sybase"], + "no FOR UPDATE NOWAIT support" + ) + + @property + def subqueries(self): + """Target database must support subqueries.""" + + return skip_if(exclude('mysql', '<', (4, 1, 1)), 'no subquery support') + + @property + def intersect(self): + """Target database must support INTERSECT or equivalent.""" + + return fails_if([ + "firebird", "mysql", "sybase", "informix" + ], 'no support for INTERSECT') + + @property + def except_(self): + """Target database must support EXCEPT or equivalent (i.e. MINUS).""" + return fails_if([ + "firebird", "mysql", "sybase", "informix" + ], 'no support for EXCEPT') + + @property + def offset(self): + """Target database must support some method of adding OFFSET or + equivalent to a result set.""" + return fails_if([ + "sybase" + ], 'no support for OFFSET or equivalent') + + @property + def window_functions(self): + return only_if([ + "postgresql", "mssql", "oracle" + ], "Backend does not support window functions") + + @property + def returning(self): + return only_if(["postgresql", "mssql", "oracle", "firebird"], + "'returning' not supported by database" + ) + + @property + def two_phase_transactions(self): + """Target database must support two-phase transactions.""" + + return skip_if([ + no_support('access', 'two-phase xact not supported by database'), + no_support('firebird', 'no SA implementation'), + no_support('maxdb', 'two-phase xact not supported by database'), + no_support('mssql', 'two-phase xact not supported by drivers'), + no_support('oracle', 'two-phase xact not implemented in SQLA/oracle'), + no_support('drizzle', 'two-phase xact not supported by database'), + no_support('sqlite', 'two-phase xact not supported by database'), + no_support('sybase', 'two-phase xact not supported by drivers/SQLA'), + no_support('postgresql+zxjdbc', + 'FIXME: JDBC driver confuses the transaction state, may ' + 'need separate XA implementation'), + exclude('mysql', '<', (5, 0, 3), + 'two-phase xact not supported by database'), + ]) + + @property + def views(self): + """Target database must support VIEWs.""" + + return skip_if("drizzle", "no VIEW support") + + @property + def unicode_connections(self): + """Target driver must support some encoding of Unicode across the wire.""" + # TODO: expand to exclude MySQLdb versions w/ broken unicode + return skip_if([ + exclude('mysql', '<', (4, 1, 1), 'no unicode connection support'), + ]) + + @property + def unicode_ddl(self): + """Target driver must support some encoding of Unicode across the wire.""" + # TODO: expand to exclude MySQLdb versions w/ broken unicode + return skip_if([ + no_support('maxdb', 'database support flakey'), + no_support('oracle', 'FIXME: no support in database?'), + no_support('sybase', 'FIXME: guessing, needs confirmation'), + no_support('mssql+pymssql', 'no FreeTDS support'), + exclude('mysql', '<', (4, 1, 1), 'no unicode connection support'), + ]) + + @property + def sane_rowcount(self): + return skip_if( + lambda: not self.db.dialect.supports_sane_rowcount, + "driver doesn't support 'sane' rowcount" + ) + + @property + def cextensions(self): + return skip_if( + lambda: not self._has_cextensions(), "C extensions not installed" + ) + + + @property + def emulated_lastrowid(self): + """"target dialect retrieves cursor.lastrowid or an equivalent + after an insert() construct executes. + """ + return fails_on_everything_except('mysql+mysqldb', 'mysql+oursql', + 'sqlite+pysqlite', 'mysql+pymysql', + 'mssql+pyodbc', 'mssql+mxodbc') + + @property + def dbapi_lastrowid(self): + """"target backend includes a 'lastrowid' accessor on the DBAPI + cursor object. + + """ + return fails_on_everything_except('mysql+mysqldb', 'mysql+oursql', + 'sqlite+pysqlite', 'mysql+pymysql') + + @property + def sane_multi_rowcount(self): + return skip_if( + lambda: not self.db.dialect.supports_sane_multi_rowcount, + "driver doesn't support 'sane' multi row count" + ) + + @property + def nullsordering(self): + """Target backends that support nulls ordering.""" + return _chain_decorators_on( + fails_on_everything_except('postgresql', 'oracle', 'firebird') + ) + + @property + def reflects_pk_names(self): + """Target driver reflects the name of primary key constraints.""" + return _chain_decorators_on( + fails_on_everything_except('postgresql', 'oracle') + ) + + @property + def python2(self): + return _chain_decorators_on( + skip_if( + lambda: sys.version_info >= (3,), + "Python version 2.xx is required." + ) + ) + + @property + def python3(self): + return _chain_decorators_on( + skip_if( + lambda: sys.version_info < (3,), + "Python version 3.xx is required." + ) + ) + + @property + def python26(self): + return _chain_decorators_on( + skip_if( + lambda: sys.version_info < (2, 6), + "Python version 2.6 or greater is required" ) + ) -def nullsordering(fn): - """Target backends that support nulls ordering.""" - return _chain_decorators_on( - fn, - fails_on_everything_except('postgresql', 'oracle', 'firebird') - ) - -def reflects_pk_names(fn): - """Target driver reflects the name of primary key constraints.""" - return _chain_decorators_on( - fn, - fails_on_everything_except('postgresql', 'oracle') - ) - -def python2(fn): - return _chain_decorators_on( - fn, - skip_if( - lambda: sys.version_info >= (3,), - "Python version 2.xx is required." + @property + def python25(self): + return _chain_decorators_on( + skip_if( + lambda: sys.version_info < (2, 5), + "Python version 2.5 or greater is required" ) - ) - -def python3(fn): - return _chain_decorators_on( - fn, - skip_if( - lambda: sys.version_info < (3,), - "Python version 3.xx is required." + ) + + @property + def cpython(self): + return _chain_decorators_on( + only_if(lambda: util.cpython, + "cPython interpreter needed" + ) + ) + + @property + def predictable_gc(self): + """target platform must remove all cycles unconditionally when + gc.collect() is called, as well as clean out unreferenced subclasses. + + """ + return self.cpython + + @property + def sqlite(self): + return _chain_decorators_on( + skip_if(lambda: not self._has_sqlite()) + ) + + @property + def ad_hoc_engines(self): + """Test environment must allow ad-hoc engine/connection creation. + + DBs that scale poorly for many connections, even when closed, i.e. + Oracle, may use the "--low-connections" option which flags this requirement + as not present. + + """ + return _chain_decorators_on( + skip_if(lambda: config.options.low_connections) + ) + + @property + def skip_mysql_on_windows(self): + """Catchall for a large variety of MySQL on Windows failures""" + + return _chain_decorators_on( + skip_if(self._has_mysql_on_windows, + "Not supported on MySQL + Windows" ) - ) - -def python26(fn): - return _chain_decorators_on( - fn, - skip_if( - lambda: sys.version_info < (2, 6), - "Python version 2.6 or greater is required" ) - ) - -def python25(fn): - return _chain_decorators_on( - fn, - skip_if( - lambda: sys.version_info < (2, 5), - "Python version 2.5 or greater is required" + + @property + def english_locale_on_postgresql(self): + return _chain_decorators_on( + skip_if(lambda: against('postgresql') \ + and not self.db.scalar('SHOW LC_COLLATE').startswith('en')) ) - ) - -def cpython(fn): - return _chain_decorators_on( - fn, - only_if(lambda: util.cpython, - "cPython interpreter needed" - ) - ) - -def predictable_gc(fn): - """target platform must remove all cycles unconditionally when - gc.collect() is called, as well as clean out unreferenced subclasses. - - """ - return cpython(fn) - -def sqlite(fn): - return _chain_decorators_on( - fn, - skip_if(lambda: not _has_sqlite()) - ) - -def ad_hoc_engines(fn): - """Test environment must allow ad-hoc engine/connection creation. - - DBs that scale poorly for many connections, even when closed, i.e. - Oracle, may use the "--low-connections" option which flags this requirement - as not present. - - """ - return _chain_decorators_on( - fn, - skip_if(lambda: config.options.low_connections) - ) - -def skip_mysql_on_windows(fn): - """Catchall for a large variety of MySQL on Windows failures""" - - return _chain_decorators_on( - fn, - skip_if(_has_mysql_on_windows, - "Not supported on MySQL + Windows" + + @property + def selectone(self): + """target driver must support the literal statement 'select 1'""" + return _chain_decorators_on( + skip_if(lambda: against('oracle'), + "non-standard SELECT scalar syntax"), + skip_if(lambda: against('firebird'), + "non-standard SELECT scalar syntax") ) - ) - -def english_locale_on_postgresql(fn): - return _chain_decorators_on( - fn, - skip_if(lambda: testing.against('postgresql') \ - and not testing.db.scalar('SHOW LC_COLLATE').startswith('en')) - ) - -def selectone(fn): - """target driver must support the literal statement 'select 1'""" - return _chain_decorators_on( - fn, - skip_if(lambda: testing.against('oracle'), - "non-standard SELECT scalar syntax"), - skip_if(lambda: testing.against('firebird'), - "non-standard SELECT scalar syntax") - ) - -def _has_cextensions(): - try: - from sqlalchemy import cresultproxy, cprocessors - return True - except ImportError: - return False - -def _has_sqlite(): - from sqlalchemy import create_engine - try: - e = create_engine('sqlite://') - return True - except ImportError: - return False - -def _has_mysql_on_windows(): - return testing.against('mysql') and \ - testing.db.dialect._detect_casing(testing.db) == 1 - -def _has_mysql_fully_case_sensitive(): - return testing.against('mysql') and \ - testing.db.dialect._detect_casing(testing.db) == 0 + + def _has_cextensions(self): + try: + from sqlalchemy import cresultproxy, cprocessors + return True + except ImportError: + return False + + def _has_sqlite(self): + from sqlalchemy import create_engine + try: + create_engine('sqlite://') + return True + except ImportError: + return False + + def _has_mysql_on_windows(self): + return against('mysql') and \ + self.db.dialect._detect_casing(self.db) == 1 + + def _has_mysql_fully_case_sensitive(self): + return against('mysql') and \ + self.db.dialect._detect_casing(self.db) == 0 |
