removed from Numeric/Float.
postgresql and sqlite. [ticket:443]
- dialect refactor
+ - the "owner" keyword argument is removed from Table. Use "schema" to
+ represent any namespaces to be prepended to the table name.
- server_version_info becomes a static attribute.
- dialects receive an initialize() event on initial connection to
determine connection properties.
- dialects receive a visit_pool event have an opportunity to
establish pool listeners.
- cached TypeEngine classes are cached per-dialect class instead of per-dialect.
+ - Deprecated Dialect.get_params() removed.
+ - Dialect.get_rowcount() has been renamed to a descriptor "rowcount", and calls
+ cursor.rowcount directly. Dialects which need to hardwire a rowcount in for
+ certain calls should override the method to provide different behavior.
+
- mysql
- all the _detect_XXX() functions now run once underneath dialect.initialize()
unless the "comparator" argument with a comparsion function is specified to the type.
Objects being pickled will be compared based on identity (which defeats the purpose
of mutable=True) if __eq__() is not overridden or a comparison function is not provided.
+ - The default "precision" and "scale" arguments of Numeric and Float have been removed
+ and now default to None. NUMERIC and FLOAT will be rendered with no numeric arguments
+ by default unless these values are provided.
\ No newline at end of file
return MaxDBResultProxy(self)
return engine_base.ResultProxy(self)
+ @property
+ def rowcount(self):
+ if hasattr(self, '_rowcount'):
+ return self._rowcount
+ else:
+ return self.cursor.rowcount
class MaxDBCachedColumnRow(engine_base.RowProxy):
"""A RowProxy that only runs result_processors once per column."""
-from sqlalchemy import Table, MetaData, Column, ForeignKey, String, Integer
+from sqlalchemy import Table, MetaData, Column, ForeignKey, String, Unicode, Integer
ischema = MetaData()
schemata = Table("SCHEMATA", ischema,
- Column("CATALOG_NAME", String, key="catalog_name"),
- Column("SCHEMA_NAME", String, key="schema_name"),
- Column("SCHEMA_OWNER", String, key="schema_owner"),
+ Column("CATALOG_NAME", Unicode, key="catalog_name"),
+ Column("SCHEMA_NAME", Unicode, key="schema_name"),
+ Column("SCHEMA_OWNER", Unicode, key="schema_owner"),
schema="INFORMATION_SCHEMA")
tables = Table("TABLES", ischema,
- Column("TABLE_CATALOG", String, key="table_catalog"),
- Column("TABLE_SCHEMA", String, key="table_schema"),
- Column("TABLE_NAME", String, key="table_name"),
+ Column("TABLE_CATALOG", Unicode, key="table_catalog"),
+ Column("TABLE_SCHEMA", Unicode, key="table_schema"),
+ Column("TABLE_NAME", Unicode, key="table_name"),
Column("TABLE_TYPE", String, key="table_type"),
schema="INFORMATION_SCHEMA")
columns = Table("COLUMNS", ischema,
- Column("TABLE_SCHEMA", String, key="table_schema"),
- Column("TABLE_NAME", String, key="table_name"),
- Column("COLUMN_NAME", String, key="column_name"),
+ Column("TABLE_SCHEMA", Unicode, key="table_schema"),
+ Column("TABLE_NAME", Unicode, key="table_name"),
+ Column("COLUMN_NAME", Unicode, key="column_name"),
Column("IS_NULLABLE", Integer, key="is_nullable"),
Column("DATA_TYPE", String, key="data_type"),
Column("ORDINAL_POSITION", Integer, key="ordinal_position"),
schema="INFORMATION_SCHEMA")
constraints = Table("TABLE_CONSTRAINTS", ischema,
- Column("TABLE_SCHEMA", String, key="table_schema"),
- Column("TABLE_NAME", String, key="table_name"),
- Column("CONSTRAINT_NAME", String, key="constraint_name"),
+ Column("TABLE_SCHEMA", Unicode, key="table_schema"),
+ Column("TABLE_NAME", Unicode, key="table_name"),
+ Column("CONSTRAINT_NAME", Unicode, key="constraint_name"),
Column("CONSTRAINT_TYPE", String, key="constraint_type"),
schema="INFORMATION_SCHEMA")
column_constraints = Table("CONSTRAINT_COLUMN_USAGE", ischema,
- Column("TABLE_SCHEMA", String, key="table_schema"),
- Column("TABLE_NAME", String, key="table_name"),
- Column("COLUMN_NAME", String, key="column_name"),
- Column("CONSTRAINT_NAME", String, key="constraint_name"),
+ Column("TABLE_SCHEMA", Unicode, key="table_schema"),
+ Column("TABLE_NAME", Unicode, key="table_name"),
+ Column("COLUMN_NAME", Unicode, key="column_name"),
+ Column("CONSTRAINT_NAME", Unicode, key="constraint_name"),
schema="INFORMATION_SCHEMA")
key_constraints = Table("KEY_COLUMN_USAGE", ischema,
- Column("TABLE_SCHEMA", String, key="table_schema"),
- Column("TABLE_NAME", String, key="table_name"),
- Column("COLUMN_NAME", String, key="column_name"),
- Column("CONSTRAINT_NAME", String, key="constraint_name"),
+ Column("TABLE_SCHEMA", Unicode, key="table_schema"),
+ Column("TABLE_NAME", Unicode, key="table_name"),
+ Column("COLUMN_NAME", Unicode, key="column_name"),
+ Column("CONSTRAINT_NAME", Unicode, key="constraint_name"),
Column("ORDINAL_POSITION", Integer, key="ordinal_position"),
schema="INFORMATION_SCHEMA")
ref_constraints = Table("REFERENTIAL_CONSTRAINTS", ischema,
- Column("CONSTRAINT_CATALOG", String, key="constraint_catalog"),
- Column("CONSTRAINT_SCHEMA", String, key="constraint_schema"),
- Column("CONSTRAINT_NAME", String, key="constraint_name"),
- Column("UNIQUE_CONSTRAINT_CATLOG", String, key="unique_constraint_catalog"),
- Column("UNIQUE_CONSTRAINT_SCHEMA", String, key="unique_constraint_schema"),
- Column("UNIQUE_CONSTRAINT_NAME", String, key="unique_constraint_name"),
+ Column("CONSTRAINT_CATALOG", Unicode, key="constraint_catalog"),
+ Column("CONSTRAINT_SCHEMA", Unicode, key="constraint_schema"),
+ Column("CONSTRAINT_NAME", Unicode, key="constraint_name"),
+ Column("UNIQUE_CONSTRAINT_CATLOG", Unicode, key="unique_constraint_catalog"), # TODO: is CATLOG misspelled ?
+ Column("UNIQUE_CONSTRAINT_SCHEMA", Unicode, key="unique_constraint_schema"),
+ Column("UNIQUE_CONSTRAINT_NAME", Unicode, key="unique_constraint_name"),
Column("MATCH_OPTION", String, key="match_option"),
Column("UPDATE_RULE", String, key="update_rule"),
Column("DELETE_RULE", String, key="delete_rule"),
schema="INFORMATION_SCHEMA")
views = Table("VIEWS", ischema,
- Column("TABLE_CATALOG", String, key="table_catalog"),
- Column("TABLE_SCHEMA", String, key="table_schema"),
- Column("TABLE_NAME", String, key="table_name"),
- Column("VIEW_DEFINITION", String, key="view_definition"),
+ Column("TABLE_CATALOG", Unicode, key="table_catalog"),
+ Column("TABLE_SCHEMA", Unicode, key="table_schema"),
+ Column("TABLE_NAME", Unicode, key="table_name"),
+ Column("VIEW_DEFINITION", Unicode, key="view_definition"),
Column("CHECK_OPTION", String, key="check_option"),
Column("IS_UPDATABLE", String, key="is_updatable"),
schema="INFORMATION_SCHEMA")
return rows
class ReflectedState(object):
+ """Stores raw information about a SHOW CREATE TABLE statement."""
+
def __init__(self):
self.columns = []
self.table_options = {}
self.constraints = []
class MySQLTableDefinitionParser(object):
-
- def __init__(self, dialect, preparer=None):
- """Construct a MySQLSchemaReflector.
-
- identifier_preparer
- An ANSIIdentifierPreparer type, used to determine the identifier
- quoting style in effect.
- """
-
+ """Parses the results of a SHOW CREATE TABLE statement."""
+
+ def __init__(self, dialect, preparer):
self.dialect = dialect
- self.preparer = preparer or dialect.identifier_preparer
+ self.preparer = preparer
self._prep_regexes()
def parse(self, show_create, charset):
def _lastrowid(self, cursor):
return cursor.lastrowid
+ @property
+ def rowcount(self):
+ if hasattr(self, '_rowcount'):
+ return self._rowcount
+ else:
+ return self.cursor.rowcount
+
+
class MySQL_mysqldbCompiler(MySQLCompiler):
operators = util.update_copy(
MySQLCompiler.operators,
preparer = OracleIdentifierPreparer
defaultrunner = OracleDefaultRunner
+ reflection_options = ('oracle_resolve_synonyms', )
+
+
def __init__(self,
use_ansi=True,
optimize_limits=False,
c. Specifying types where there is an analogue in sqlalchemy.types,
but the database in use takes vendor-specific flags for those
types.
+
+ d. If a TypeEngine class doesn't provide any of this, it should be
+ *removed* from the dialect.
2. the TypeEngine classes are *no longer* used for:
a. The string name should be matched to the most specific type possible within
sqlalchemy.types, unless there is no matching type within sqlalchemy.types in which
- case it points to a dialect type.
+ case it points to a dialect type. *It doesn't matter* if the dialect has it's
+ own subclass of that type with special bind/result behavior - reflect to the generic type
+ as much as possible, since the correct bind/result behavior is always invoked when needed
+ regardless of the type being generic or dialect-specific.
+
+ b. If the dialect contains a matching dialect-specific type that takes extra arguments
+ which the generic one does not, then point to the dialect-specific type. E.g.
+ mssql MSString takes a "collation" parameter which should be preserved.
- b. For an exact or almost exact match, point to the uppercase type. i.e. "float"
+ c. For an exact or almost exact match, point to the uppercase type. i.e. "float"
should point to "FLOAT", "varchar" should point to "VARCHAR"
- c. for a non-match, point to the lowercase type. i.e. "long" should point to "Text",
+ d. for a non-match, point to the lowercase type. i.e. "long" should point to "Text",
"special varchar with sprinkles" points to "String".
5. DDL, or what was formerly issued by "get_col_spec()", is now handled exclusively by
return self.string or ''
- @util.deprecated('Deprecated. Use construct_params(). '
- '(supports Unicode key names.)')
- def get_params(self, **params):
- return self.construct_params(params)
-
def construct_params(self, params=None):
"""Return the bind params for this compiled object.
raise NotImplementedError()
+ params = property(construct_params, doc="""
+ Return the bind params for this compiled object.
+
+ """)
+
+
def execute(self, *multiparams, **params):
"""Execute this compiled object."""
_process_row = RowProxy
def __init__(self, context):
- """ResultProxy objects are constructed via the execute() method on SQLEngine."""
self.context = context
self.dialect = context.dialect
self.closed = False
self._echo = context.engine._should_log_info
self._init_metadata()
- @property
+ @util.memoized_property
def rowcount(self):
- if self._rowcount is None:
- return self.context.get_rowcount()
- else:
- return self._rowcount
+ return self.context.rowcount
@property
def lastrowid(self):
if metadata is None:
# no results, get rowcount (which requires open cursor on some DB's such as firebird),
# then close
- self._rowcount = self.context.get_rowcount()
+ self.rowcount
self.close()
return
- self._rowcount = None
self._props = util.populate_column_dict(None)
self._props.creator = self.__key_fallback()
self.keys = []
default_paramstyle = 'named'
supports_default_values = False
supports_empty_insert = True
+ reflection_options = ()
def __init__(self, convert_unicode=False, assert_unicode=False,
encoding='utf-8', paramstyle=None, dbapi=None,
self.description_encoding = getattr(self, 'description_encoding', encoding)
# Py3K
+ ## work around dialects that might change these values
#self.supports_unicode_statements = True
#self.supports_unicode_binds = True
def initialize(self, connection):
- # TODO: all dialects need to implement this
if hasattr(self, '_get_server_version_info'):
self.server_version_info = self._get_server_version_info(connection)
def get_result_proxy(self):
return base.ResultProxy(self)
-
- def get_rowcount(self):
- if hasattr(self, '_rowcount'):
- return self._rowcount
- else:
- return self.cursor.rowcount
+
+ @property
+ def rowcount(self):
+ return self.cursor.rowcount
def supports_sane_rowcount(self):
return self.dialect.supports_sane_rowcount
dialect._adjust_casing(table)
# table attributes we might need.
- oracle_resolve_synonyms = table.kwargs.get('oracle_resolve_synonyms',
- False)
-
- # some properties that need to be figured out
- fk_use_existing = True
+ reflection_options = dict((k, table.kwargs.get(k)) for k in dialect.reflection_options if k in table.kwargs)
schema = table.schema
table_name = table.name
tblkw[str(k)] = v
### Py2K
- # fixme
- # This is breaking mssql, which can't bind unicode.
- ##if isinstance(schema, str):
- ## schema = schema.decode(dialect.encoding)
- ##if isinstance(table_name, str):
- ## table_name = table_name.decode(dialect.encoding)
+ if isinstance(schema, str):
+ schema = schema.decode(dialect.encoding)
+ if isinstance(table_name, str):
+ table_name = table_name.decode(dialect.encoding)
# end Py2K
# columns
if pk in table.c:
col = table.c[pk]
table.primary_key.add(col)
- # fixme
- if not isinstance(dialect, MySQLDialect):
- if col.default is None:
- col.autoincrement = False
# Foreign keys
fkeys = self.get_foreign_keys(table_name, schema, **tblkw)
for fkey_d in fkeys:
sa_schema.Table(referred_table, table.metadata,
autoload=True, schema=referred_schema,
autoload_with=self.conn,
- oracle_resolve_synonyms=oracle_resolve_synonyms,
- useexisting=fk_use_existing
+ **reflection_options
)
for column in referred_columns:
refspec.append(".".join(
else:
sa_schema.Table(referred_table, table.metadata, autoload=True,
autoload_with=self.conn,
- oracle_resolve_synonyms=oracle_resolve_synonyms,
- useexisting=fk_use_existing
+ **reflection_options
)
for column in referred_columns:
refspec.append(".".join([referred_table, column]))
Provides a ``create`` method that receives input arguments and
produces an instance of base.Engine or a subclass.
+
"""
- def __init__(self, name):
- """Construct a new EngineStrategy object.
-
- Sets it in the list of available strategies under this name.
- """
-
- self.name = name
+ def __init__(self):
strategies[self.name] = self
def create(self, *args, **kwargs):
class DefaultEngineStrategy(EngineStrategy):
"""Base class for built-in stratgies."""
+ pool_threadlocal = False
+
def create(self, name_or_url, **kwargs):
# create url.URL object
u = url.make_url(name_or_url)
tk = translate.get(k, k)
if tk in kwargs:
pool_args[k] = kwargs.pop(tk)
- pool_args.setdefault('use_threadlocal', self.pool_threadlocal())
+ pool_args.setdefault('use_threadlocal', self.pool_threadlocal)
pool = poolclass(creator, **pool_args)
else:
if isinstance(pool, poollib._DBProxy):
pool = pool
# create engine.
- engineclass = self.get_engine_cls()
+ engineclass = self.engine_cls
engine_args = {}
for k in util.get_cls_kwargs(engineclass):
if k in kwargs:
engine = engineclass(pool, dialect, u, **engine_args)
if _initialize:
+ # some unit tests pass through _initialize=False
+ # to help mock engines work
class OnInit(object):
def first_connect(self, conn, rec):
c = base.Connection(engine, connection=conn)
return engine
- def pool_threadlocal(self):
- raise NotImplementedError()
-
- def get_engine_cls(self):
- raise NotImplementedError()
-
class PlainEngineStrategy(DefaultEngineStrategy):
"""Strategy for configuring a regular Engine."""
- def __init__(self):
- DefaultEngineStrategy.__init__(self, 'plain')
-
- def pool_threadlocal(self):
- return False
-
- def get_engine_cls(self):
- return base.Engine
-
+ name = 'plain'
+ engine_cls = base.Engine
+
PlainEngineStrategy()
class ThreadLocalEngineStrategy(DefaultEngineStrategy):
"""Strategy for configuring an Engine with thredlocal behavior."""
-
- def __init__(self):
- DefaultEngineStrategy.__init__(self, 'threadlocal')
-
- def pool_threadlocal(self):
- return True
-
- def get_engine_cls(self):
- return threadlocal.TLEngine
+
+ name = 'threadlocal'
+ pool_threadlocal = True
+ engine_cls = threadlocal.TLEngine
ThreadLocalEngineStrategy()
Produces a single mock Connectable object which dispatches
statement execution to a passed-in function.
+
"""
- def __init__(self):
- EngineStrategy.__init__(self, 'mock')
-
+ name = 'mock'
+
def create(self, name_or_url, executor, **kwargs):
# create url.URL object
u = url.make_url(name_or_url)
"""An adaptation of Py2.3/2.4's Queue module which supports reentrant
behavior, using RLock instead of Lock for its mutex object.
-This is to support the connection pool's usage of ``__del__`` to return
-connections to the underlying Queue, which can apparently in extremely
+This is to support the connection pool's usage of weakref callbacks to return
+connections to the underlying Queue, which can in extremely
rare cases be invoked within the ``get()`` method of the Queue itself,
producing a ``put()`` inside the ``get()`` and therefore a reentrant
condition."""
"""A metaclass used by the ``Table`` object to provide singleton behavior."""
def __call__(self, name, metadata, *args, **kwargs):
- schema = kwargs.get('schema', kwargs.get('owner', None))
+ schema = kwargs.get('schema', None)
useexisting = kwargs.pop('useexisting', False)
mustexist = kwargs.pop('mustexist', False)
key = _get_table_key(name, schema)
try:
table = metadata.tables[key]
- if not useexisting and table._cant_override(*args, **kwargs):
+ if not useexisting and bool(args):
+ import pdb
+ pdb.set_trace()
raise exc.InvalidRequestError(
"Table '%s' is already defined for this MetaData instance. "
"Specify 'useexisting=True' to redefine options and "
"""
super(Table, self).__init__(name)
self.metadata = metadata
- self.schema = kwargs.pop('schema', kwargs.pop('owner', None))
+ self.schema = kwargs.pop('schema', None)
self.indexes = set()
self.constraints = set()
self._columns = expression.ColumnCollection()
self.__extra_kwargs(**kwargs)
self.__post_init(*args, **kwargs)
- def _cant_override(self, *args, **kwargs):
- """Return True if any argument is not supported as an override.
-
- Takes arguments that would be sent to Table.__init__, and returns
- True if any of them would be disallowed if sent to an existing
- Table singleton.
- """
- return bool(args) or bool(set(kwargs).difference(
- ['autoload', 'autoload_with', 'schema', 'owner']))
-
def __extra_kwargs(self, **kwargs):
# validate remaining kwargs that they all specify DB prefixes
if len([k for k in kwargs
pd[self.bind_names[bindparam]] = bindparam.value
return pd
- params = property(construct_params)
-
def default_from(self):
"""Called when a SELECT statement has no froms, and no FROM clause is to be appended.
__visit_name__ = 'numeric'
- def __init__(self, precision=10, scale=2, asdecimal=True, length=None):
+ def __init__(self, precision=None, scale=None, asdecimal=True):
"""
Construct a Numeric.
use.
"""
- if length:
- util.warn_deprecated("'length' is deprecated for Numeric. Use 'scale'.")
- scale = length
self.precision = precision
self.scale = scale
self.asdecimal = asdecimal
__visit_name__ = 'float'
- def __init__(self, precision=10, asdecimal=False, **kwargs):
+ def __init__(self, precision=None, asdecimal=False, **kwargs):
"""
Construct a Float.
'dbtype://username:apples%2Foranges@hostspec/mydatabase',
):
u = url.make_url(text)
- print u, text
- print "username=", u.username, "password=", u.password, "database=", u.database, "host=", u.host
assert u.drivername == 'dbtype'
assert u.username == 'username' or u.username is None
assert u.password == 'password' or u.password == 'apples/oranges' or u.password is None
# coverage on other dialects.
sel = select([tbl, cast(tbl.c.v1, Numeric)]).compile(dialect=dialect)
if isinstance(dialect, type(mysql.dialect())):
- self.assertEqual(str(sel), "SELECT casttest.id, casttest.v1, casttest.v2, casttest.ts, CAST(casttest.v1 AS DECIMAL(10, 2)) AS anon_1 \nFROM casttest")
+ self.assertEqual(str(sel), "SELECT casttest.id, casttest.v1, casttest.v2, casttest.ts, CAST(casttest.v1 AS DECIMAL) AS anon_1 \nFROM casttest")
else:
- self.assertEqual(str(sel), "SELECT casttest.id, casttest.v1, casttest.v2, casttest.ts, CAST(casttest.v1 AS NUMERIC(10, 2)) AS anon_1 \nFROM casttest")
+ self.assertEqual(str(sel), "SELECT casttest.id, casttest.v1, casttest.v2, casttest.ts, CAST(casttest.v1 AS NUMERIC) AS anon_1 \nFROM casttest")
# first test with Postgres engine
- check_results(postgres.dialect(), ['NUMERIC(10, 2)', 'NUMERIC(12, 9)', 'DATE', 'TEXT', 'VARCHAR(20)'], '%(param_1)s')
+ check_results(postgres.dialect(), ['NUMERIC', 'NUMERIC(12, 9)', 'DATE', 'TEXT', 'VARCHAR(20)'], '%(param_1)s')
# then the Oracle engine
- check_results(oracle.dialect(), ['NUMERIC(10, 2)', 'NUMERIC(12, 9)', 'DATE', 'CLOB', 'VARCHAR(20)'], ':param_1')
+ check_results(oracle.dialect(), ['NUMERIC', 'NUMERIC(12, 9)', 'DATE', 'CLOB', 'VARCHAR(20)'], ':param_1')
# then the sqlite engine
- check_results(sqlite.dialect(), ['NUMERIC(10, 2)', 'NUMERIC(12, 9)', 'DATE', 'TEXT', 'VARCHAR(20)'], '?')
+ check_results(sqlite.dialect(), ['NUMERIC', 'NUMERIC(12, 9)', 'DATE', 'TEXT', 'VARCHAR(20)'], '?')
# then the MySQL engine
- check_results(mysql.dialect(), ['DECIMAL(10, 2)', 'DECIMAL(12, 9)', 'DATE', 'CHAR', 'CHAR(20)'], '%s')
+ check_results(mysql.dialect(), ['DECIMAL', 'DECIMAL(12, 9)', 'DATE', 'CHAR', 'CHAR(20)'], '%s')
self.assert_compile(cast(text('NULL'), Integer), "CAST(NULL AS INTEGER)", dialect=sqlite.dialect())
self.assert_compile(cast(null(), Integer), "CAST(NULL AS INTEGER)", dialect=sqlite.dialect())
(table1.c.name, 'name', 'mytable.name', None),
(table1.c.myid==12, 'mytable.myid = :myid_1', 'mytable.myid = :myid_1', 'anon_1'),
(func.hoho(table1.c.myid), 'hoho(mytable.myid)', 'hoho(mytable.myid)', 'hoho_1'),
- (cast(table1.c.name, sqlite.SLNumeric), 'CAST(mytable.name AS NUMERIC(10, 2))', 'CAST(mytable.name AS NUMERIC(10, 2))', 'anon_1'),
+ (cast(table1.c.name, sqlite.SLNumeric), 'CAST(mytable.name AS NUMERIC)', 'CAST(mytable.name AS NUMERIC)', 'anon_1'),
(t1.c.col1, 'col1', 'mytable.col1', None),
(column('some wacky thing'), 'some wacky thing', '"some wacky thing"', '')
):
assert isinstance(row['ncasdec'], decimal.Decimal)
assert isinstance(row['fcasdec'], decimal.Decimal)
- def test_length_deprecation(self):
- self.assertRaises(exc.SADeprecationWarning, Numeric, length=8)
-
- @testing.uses_deprecated(".*is deprecated for Numeric")
- def go():
- n = Numeric(length=12)
- assert n.scale == 12
- go()
-
- n = Numeric(scale=12)
- for dialect in engines.all_dialects():
- n2 = dialect.type_descriptor(n)
- eq_(n2.scale, 12, dialect.name)
-
- # test colspec generates successfully using 'scale'
- assert dialect.type_compiler.process(n2)
-
- # test constructor of the dialect-specific type
- n3 = n2.__class__(scale=5)
- eq_(n3.scale, 5, dialect.name)
-
- @testing.uses_deprecated(".*is deprecated for Numeric")
- def go():
- n3 = n2.__class__(length=6)
- eq_(n3.scale, 6, dialect.name)
- go()
-
class IntervalTest(TestBase, AssertsExecutionResults):
def setUpAll(self):