[3] | 1 | import logging |
---|
| 2 | import os |
---|
| 3 | import re |
---|
| 4 | import sys |
---|
| 5 | import time |
---|
| 6 | import warnings |
---|
| 7 | import ConfigParser |
---|
| 8 | import StringIO |
---|
| 9 | from config import db, db_label, db_url, file_config, base_config, \ |
---|
| 10 | post_configure, \ |
---|
| 11 | _list_dbs, _server_side_cursors, _engine_strategy, \ |
---|
| 12 | _engine_uri, _require, _engine_pool, \ |
---|
| 13 | _create_testing_engine, _prep_testing_database, \ |
---|
| 14 | _set_table_options, _reverse_topological, _log |
---|
| 15 | from sqlalchemy.test import testing, config, requires |
---|
| 16 | from nose.plugins import Plugin |
---|
| 17 | from nose.util import tolist |
---|
| 18 | import nose.case |
---|
| 19 | |
---|
| 20 | log = logging.getLogger('nose.plugins.sqlalchemy') |
---|
| 21 | |
---|
| 22 | class NoseSQLAlchemy(Plugin): |
---|
| 23 | """ |
---|
| 24 | Handles the setup and extra properties required for testing SQLAlchemy |
---|
| 25 | """ |
---|
| 26 | enabled = True |
---|
| 27 | name = 'sqlalchemy' |
---|
| 28 | score = 100 |
---|
| 29 | |
---|
| 30 | def options(self, parser, env=os.environ): |
---|
| 31 | Plugin.options(self, parser, env) |
---|
| 32 | opt = parser.add_option |
---|
| 33 | #opt("--verbose", action="store_true", dest="verbose", |
---|
| 34 | #help="enable stdout echoing/printing") |
---|
| 35 | #opt("--quiet", action="store_true", dest="quiet", help="suppress output") |
---|
| 36 | opt("--log-info", action="callback", type="string", callback=_log, |
---|
| 37 | help="turn on info logging for <LOG> (multiple OK)") |
---|
| 38 | opt("--log-debug", action="callback", type="string", callback=_log, |
---|
| 39 | help="turn on debug logging for <LOG> (multiple OK)") |
---|
| 40 | opt("--require", action="append", dest="require", default=[], |
---|
| 41 | help="require a particular driver or module version (multiple OK)") |
---|
| 42 | opt("--db", action="store", dest="db", default="sqlite", |
---|
| 43 | help="Use prefab database uri") |
---|
| 44 | opt('--dbs', action='callback', callback=_list_dbs, |
---|
| 45 | help="List available prefab dbs") |
---|
| 46 | opt("--dburi", action="store", dest="dburi", |
---|
| 47 | help="Database uri (overrides --db)") |
---|
| 48 | opt("--dropfirst", action="store_true", dest="dropfirst", |
---|
| 49 | help="Drop all tables in the target database first (use with caution on Oracle, MS-SQL)") |
---|
| 50 | opt("--mockpool", action="store_true", dest="mockpool", |
---|
| 51 | help="Use mock pool (asserts only one connection used)") |
---|
| 52 | opt("--enginestrategy", action="callback", type="string", |
---|
| 53 | callback=_engine_strategy, |
---|
| 54 | help="Engine strategy (plain or threadlocal, defaults to plain)") |
---|
| 55 | opt("--reversetop", action="store_true", dest="reversetop", default=False, |
---|
| 56 | help="Reverse the collection ordering for topological sorts (helps " |
---|
| 57 | "reveal dependency issues)") |
---|
| 58 | opt("--unhashable", action="store_true", dest="unhashable", default=False, |
---|
| 59 | help="Disallow SQLAlchemy from performing a hash() on mapped test objects.") |
---|
| 60 | opt("--noncomparable", action="store_true", dest="noncomparable", default=False, |
---|
| 61 | help="Disallow SQLAlchemy from performing == on mapped test objects.") |
---|
| 62 | opt("--truthless", action="store_true", dest="truthless", default=False, |
---|
| 63 | help="Disallow SQLAlchemy from truth-evaluating mapped test objects.") |
---|
| 64 | opt("--serverside", action="callback", callback=_server_side_cursors, |
---|
| 65 | help="Turn on server side cursors for PG") |
---|
| 66 | opt("--mysql-engine", action="store", dest="mysql_engine", default=None, |
---|
| 67 | help="Use the specified MySQL storage engine for all tables, default is " |
---|
| 68 | "a db-default/InnoDB combo.") |
---|
| 69 | opt("--table-option", action="append", dest="tableopts", default=[], |
---|
| 70 | help="Add a dialect-specific table option, key=value") |
---|
| 71 | |
---|
| 72 | global file_config |
---|
| 73 | file_config = ConfigParser.ConfigParser() |
---|
| 74 | file_config.readfp(StringIO.StringIO(base_config)) |
---|
| 75 | file_config.read(['test.cfg', os.path.expanduser('~/.satest.cfg')]) |
---|
| 76 | config.file_config = file_config |
---|
| 77 | |
---|
| 78 | def configure(self, options, conf): |
---|
| 79 | Plugin.configure(self, options, conf) |
---|
| 80 | |
---|
| 81 | import testing, requires |
---|
| 82 | testing.db = db |
---|
| 83 | testing.requires = requires |
---|
| 84 | |
---|
| 85 | # Lazy setup of other options (post coverage) |
---|
| 86 | for fn in post_configure: |
---|
| 87 | fn(options, file_config) |
---|
| 88 | |
---|
| 89 | def describeTest(self, test): |
---|
| 90 | return "" |
---|
| 91 | |
---|
| 92 | def wantClass(self, cls): |
---|
| 93 | """Return true if you want the main test selector to collect |
---|
| 94 | tests from this class, false if you don't, and None if you don't |
---|
| 95 | care. |
---|
| 96 | |
---|
| 97 | :Parameters: |
---|
| 98 | cls : class |
---|
| 99 | The class being examined by the selector |
---|
| 100 | |
---|
| 101 | """ |
---|
| 102 | |
---|
| 103 | if not issubclass(cls, testing.TestBase): |
---|
| 104 | return False |
---|
| 105 | else: |
---|
| 106 | if (hasattr(cls, '__whitelist__') and |
---|
| 107 | testing.db.name in cls.__whitelist__): |
---|
| 108 | return True |
---|
| 109 | else: |
---|
| 110 | return not self.__should_skip_for(cls) |
---|
| 111 | |
---|
| 112 | def __should_skip_for(self, cls): |
---|
| 113 | if hasattr(cls, '__requires__'): |
---|
| 114 | def test_suite(): return 'ok' |
---|
| 115 | for requirement in cls.__requires__: |
---|
| 116 | check = getattr(requires, requirement) |
---|
| 117 | if check(test_suite)() != 'ok': |
---|
| 118 | # The requirement will perform messaging. |
---|
| 119 | return True |
---|
| 120 | if (hasattr(cls, '__unsupported_on__') and |
---|
| 121 | testing.db.name in cls.__unsupported_on__): |
---|
| 122 | print "'%s' unsupported on DB implementation '%s'" % ( |
---|
| 123 | cls.__class__.__name__, testing.db.name) |
---|
| 124 | return True |
---|
| 125 | if (getattr(cls, '__only_on__', None) not in (None, testing.db.name)): |
---|
| 126 | print "'%s' unsupported on DB implementation '%s'" % ( |
---|
| 127 | cls.__class__.__name__, testing.db.name) |
---|
| 128 | return True |
---|
| 129 | if (getattr(cls, '__skip_if__', False)): |
---|
| 130 | for c in getattr(cls, '__skip_if__'): |
---|
| 131 | if c(): |
---|
| 132 | print "'%s' skipped by %s" % ( |
---|
| 133 | cls.__class__.__name__, c.__name__) |
---|
| 134 | return True |
---|
| 135 | for rule in getattr(cls, '__excluded_on__', ()): |
---|
| 136 | if testing._is_excluded(*rule): |
---|
| 137 | print "'%s' unsupported on DB %s version %s" % ( |
---|
| 138 | cls.__class__.__name__, testing.db.name, |
---|
| 139 | _server_version()) |
---|
| 140 | return True |
---|
| 141 | return False |
---|
| 142 | |
---|
| 143 | #def begin(self): |
---|
| 144 | #pass |
---|
| 145 | |
---|
| 146 | def beforeTest(self, test): |
---|
| 147 | testing.resetwarnings() |
---|
| 148 | |
---|
| 149 | def afterTest(self, test): |
---|
| 150 | testing.resetwarnings() |
---|
| 151 | |
---|
| 152 | #def handleError(self, test, err): |
---|
| 153 | #pass |
---|
| 154 | |
---|
| 155 | #def finalize(self, result=None): |
---|
| 156 | #pass |
---|