diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-03-02 14:49:24 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-03-02 14:49:24 -0500 |
commit | ffbc58333306c098c9c71ea28482975803467d8c (patch) | |
tree | f3fcb9451f050f0fdaf9f0b277ce8020cb258f63 | |
parent | e932c263d54bb86451e8e4c63e459388654c860b (diff) | |
download | sqlalchemy-ffbc58333306c098c9c71ea28482975803467d8c.tar.gz |
- cleanup, solidify Config
-rw-r--r-- | lib/sqlalchemy/testing/__init__.py | 3 | ||||
-rw-r--r-- | lib/sqlalchemy/testing/config.py | 54 | ||||
-rw-r--r-- | lib/sqlalchemy/testing/exclusions.py | 1 | ||||
-rw-r--r-- | lib/sqlalchemy/testing/plugin/noseplugin.py | 60 | ||||
-rw-r--r-- | lib/sqlalchemy/testing/schema.py | 6 | ||||
-rw-r--r-- | test/engine/test_reflection.py | 2 | ||||
-rw-r--r-- | test/requirements.py | 20 |
7 files changed, 92 insertions, 54 deletions
diff --git a/lib/sqlalchemy/testing/__init__.py b/lib/sqlalchemy/testing/__init__.py index 61e0f5429..954906432 100644 --- a/lib/sqlalchemy/testing/__init__.py +++ b/lib/sqlalchemy/testing/__init__.py @@ -26,6 +26,7 @@ from .util import run_as_contextmanager, rowset, fail, provide_metadata, adict crashes = skip -from .config import db, requirements as requires +from .config import db +from .config import requirements as requires from . import mock
\ No newline at end of file diff --git a/lib/sqlalchemy/testing/config.py b/lib/sqlalchemy/testing/config.py index c25355396..d75f6b545 100644 --- a/lib/sqlalchemy/testing/config.py +++ b/lib/sqlalchemy/testing/config.py @@ -4,12 +4,66 @@ # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php +import collections + requirements = None db = None +db_url = None dbs = {} db_opts = None _current = None file_config = None +class Config(object): + def __init__(self, db, db_opts, options, file_config): + self.db = db + self.db_opts = db_opts + self.options = options + self.file_config = file_config + + _stack = collections.deque() + + @classmethod + def register(cls, db, db_opts, options, file_config, namespace): + """add a config as one of the global configs. + + If there are no configs set up yet, this config also + gets set as the "_current". + """ + cfg = Config(db, db_opts, options, file_config) + + global _current + if not _current: + cls.set_as_current(cfg, namespace) + dbs[cfg.db.name] = cfg + dbs[(cfg.db.name, cfg.db.dialect)] = cfg + dbs[cfg.db] = cfg + + @classmethod + def set_as_current(cls, config, namespace): + global db, _current, db_url + _current = config + db_url = config.db.url + namespace.db = db = config.db + + @classmethod + def push_engine(cls, db, namespace): + assert _current, "Can't push without a default Config set up" + cls.push( + Config(db, _current.db_opts, _current.options, _current.file_config), + namespace + ) + + @classmethod + def push(cls, config, namespace): + cls._stack.append(_current) + cls.set_as_current(config, namespace) + + @classmethod + def reset(cls, namespace): + if cls._stack: + cls.set_as_current(cls._stack[0], namespace) + cls._stack.clear() + def _unique_configs(): return set(dbs.values())
\ No newline at end of file diff --git a/lib/sqlalchemy/testing/exclusions.py b/lib/sqlalchemy/testing/exclusions.py index c517f9049..2c642a3e8 100644 --- a/lib/sqlalchemy/testing/exclusions.py +++ b/lib/sqlalchemy/testing/exclusions.py @@ -348,6 +348,7 @@ def exclude(db, op, spec, reason=None): def against(config, *queries): + assert queries, "no queries sent!" return OrPredicate([ Predicate.as_predicate(query) for query in queries diff --git a/lib/sqlalchemy/testing/plugin/noseplugin.py b/lib/sqlalchemy/testing/plugin/noseplugin.py index 153d227a7..ed822ffc4 100644 --- a/lib/sqlalchemy/testing/plugin/noseplugin.py +++ b/lib/sqlalchemy/testing/plugin/noseplugin.py @@ -20,6 +20,7 @@ from __future__ import absolute_import import os import sys +import re py3k = sys.version_info >= (3, 0) if py3k: @@ -48,16 +49,8 @@ file_config = None logging = None db_opts = {} options = None -_existing_config_obj = None -class Config(object): - def __init__(self, db, db_opts, options, file_config): - self.db = db - self.db_opts = db_opts - self.options = options - self.file_config = file_config - def _log(option, opt_str, value, parser): global logging if not logging: @@ -119,13 +112,14 @@ def _engine_uri(options, file_config): db_urls = [] if options.db: - for db in options.db: - if db not in file_config.options('db'): - raise RuntimeError( - "Unknown URI specifier '%s'. Specify --dbs for known uris." - % db) - else: - db_urls.append(file_config.get('db', db)) + for db_token in options.db: + for db in re.split(r'[,\s]+', db_token): + if db not in file_config.options('db'): + raise RuntimeError( + "Unknown URI specifier '%s'. Specify --dbs for known uris." + % db) + else: + db_urls.append(file_config.get('db', db)) if not db_urls: db_urls.append(file_config.get('db', 'default')) @@ -133,13 +127,7 @@ def _engine_uri(options, file_config): for db_url in db_urls: eng = engines.testing_engine(db_url, db_opts) eng.connect().close() - config_obj = Config(eng, db_opts, options, file_config) - if not config.db: - config.db = testing.db = eng - config._current = config_obj - config.dbs[eng.name] = config_obj - config.dbs[(eng.name, eng.dialect)] = config_obj - config.dbs[eng] = config_obj + config.Config.register(eng, db_opts, options, file_config, testing) config.db_opts = db_opts @@ -385,7 +373,9 @@ class NoseSQLAlchemy(Plugin): for db_spec, op, spec in getattr(cls, '__excluded_on__', ()): for config_obj in list(all_configs): - if exclusions.skip_if(exclusions.SpecPredicate(db_spec, op, spec)).predicate(config_obj): + if exclusions.skip_if( + exclusions.SpecPredicate(db_spec, op, spec) + ).predicate(config_obj): all_configs.remove(config_obj) @@ -393,7 +383,9 @@ class NoseSQLAlchemy(Plugin): raise SkipTest( "'%s' unsupported on DB implementation %s%s" % ( cls.__name__, - ", ".join("'%s' = %s" % (config_obj.db.name, config_obj.db.dialect.server_version_info) + ", ".join("'%s' = %s" % ( + config_obj.db.name, + config_obj.db.dialect.server_version_info) for config_obj in config._unique_configs() ), ", ".join(reasons) @@ -420,29 +412,15 @@ class NoseSQLAlchemy(Plugin): warnings.resetwarnings() def _setup_config(self, config_obj, ctx): - ctx.__use_config__ = config_obj + config._current.push(config_obj, testing) def _setup_engine(self, ctx): if getattr(ctx, '__engine_options__', None): eng = engines.testing_engine(options=ctx.__engine_options__) - config_obj = Config(eng, db_opts, options, file_config) - elif getattr(ctx, '__use_config__', None): - config_obj = ctx.__use_config__ - else: - config_obj = None - - if config_obj: - global _existing_config_obj - _existing_config_obj = config._current - config._current = config_obj - config.db = testing.db = config_obj.db + config._current.push_engine(eng) def _restore_engine(self, ctx): - global _existing_config_obj - if _existing_config_obj is not None: - config.db = testing.db = _existing_config_obj.db - config._current = _existing_config_obj - _existing_config_obj = None + config._current.reset(testing) def startContext(self, ctx): if not isinstance(ctx, type) \ diff --git a/lib/sqlalchemy/testing/schema.py b/lib/sqlalchemy/testing/schema.py index 605ca86b8..4766af180 100644 --- a/lib/sqlalchemy/testing/schema.py +++ b/lib/sqlalchemy/testing/schema.py @@ -21,7 +21,7 @@ def Table(*args, **kw): kw.update(table_options) - if exclusions.against('mysql'): + if exclusions.against(config._current, 'mysql'): if 'mysql_engine' not in kw and 'mysql_type' not in kw: if 'test_needs_fk' in test_opts or 'test_needs_acid' in test_opts: kw['mysql_engine'] = 'InnoDB' @@ -30,7 +30,7 @@ def Table(*args, **kw): # Apply some default cascading rules for self-referential foreign keys. # MySQL InnoDB has some issues around seleting self-refs too. - if exclusions.against('firebird'): + if exclusions.against(config._current, 'firebird'): table_name = args[0] unpack = (config.db.dialect. identifier_preparer.unformat_identifiers) @@ -78,7 +78,7 @@ def Column(*args, **kw): # hardcoded rule for firebird, oracle; this should # be moved out - if exclusions.against(config, 'firebird', 'oracle'): + if exclusions.against(config._current, 'firebird', 'oracle'): def add_seq(c, tbl): c._init_items( schema.Sequence(_truncate_name( diff --git a/test/engine/test_reflection.py b/test/engine/test_reflection.py index 8a1d7b70e..45ca934ce 100644 --- a/test/engine/test_reflection.py +++ b/test/engine/test_reflection.py @@ -1152,7 +1152,7 @@ class UnicodeReflectionTest(fixtures.TestBase): names = no_multibyte_period # mysql can't handle casing usually elif testing.against("mysql") and \ - not testing.requires._has_mysql_fully_case_sensitive(): + not testing.requires.mysql_fully_case_sensitive.enabled: names = no_multibyte_period.union(no_case_sensitivity) # mssql + pyodbc + freetds can't compare multibyte names to # information_schema.tables.table_name diff --git a/test/requirements.py b/test/requirements.py index 6f6945818..4d8433003 100644 --- a/test/requirements.py +++ b/test/requirements.py @@ -403,7 +403,7 @@ class DefaultRequirements(SuiteRequirements): @property def sane_rowcount(self): return skip_if( - lambda: not self.db.dialect.supports_sane_rowcount, + lambda config: not config.db.dialect.supports_sane_rowcount, "driver doesn't support 'sane' rowcount" ) @@ -443,7 +443,7 @@ class DefaultRequirements(SuiteRequirements): @property def sane_multi_rowcount(self): return skip_if( - lambda: not self.db.dialect.supports_sane_multi_rowcount, + lambda config: not config.db.dialect.supports_sane_multi_rowcount, "driver doesn't support 'sane' multi row count" ) @@ -698,7 +698,7 @@ class DefaultRequirements(SuiteRequirements): as not present. """ - return skip_if(lambda: self.config.options.low_connections) + return skip_if(lambda config: config.options.low_connections) @property def skip_mysql_on_windows(self): @@ -715,8 +715,8 @@ class DefaultRequirements(SuiteRequirements): """ return skip_if( - lambda: util.py3k and - self.config.options.enable_plugin_coverage, + lambda config: util.py3k and + config.options.enable_plugin_coverage, "Stability issues with coverage + py3k" ) @@ -740,11 +740,15 @@ class DefaultRequirements(SuiteRequirements): except ImportError: return False + @property + def mysql_fully_case_sensitive(self): + return only_if(self._has_mysql_fully_case_sensitive) + def _has_mysql_on_windows(self, config): - return against(config.db, 'mysql') and \ - self.db.dialect._detect_casing(self.db) == 1 + return against(config, 'mysql') and \ + config.db.dialect._detect_casing(config.db) == 1 def _has_mysql_fully_case_sensitive(self, config): - return against(config.db, 'mysql') and \ + return against(config, 'mysql') and \ config.db.dialect._detect_casing(config.db) == 0 |