From d2a6238372bf8050b847f5755817b5a1a16fcf10 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 1 Aug 2013 20:25:56 -0400 Subject: - assorted fixes raised by pypy 2.1beta2, but all of which are good ideas in general: - pypy2.1 w/ sqlite3 is the first DBAPI we're seeing returning unicode in cursor.description without being py3k. add a new on-connect check for this, if we get back a u"", just don't do description decoding, should be OK for now. - the set tests in test_collection were assuming the two sets would be ordered the same when it tested pop(), can't really assume that. - test_serializer gets worse and worse, pickle is just not really viable here, ding out pypy - pypy2.1b2 seems to allow cursor.lastrowid to work (or we changed something?) - pool._threadconns.current() is a weakref, it can be None - another one of those logging.handlers imports --- lib/sqlalchemy/testing/suite/test_insert.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/suite/test_insert.py b/lib/sqlalchemy/testing/suite/test_insert.py index e671eeb7a..21141f244 100644 --- a/lib/sqlalchemy/testing/suite/test_insert.py +++ b/lib/sqlalchemy/testing/suite/test_insert.py @@ -56,8 +56,9 @@ class LastrowidTest(fixtures.TablesTest): [pk] ) - @exclusions.fails_if(lambda: util.pypy, "lastrowid not maintained after " - "connection close") + # failed on pypy1.9 but seems to be OK on pypy 2.1 + #@exclusions.fails_if(lambda: util.pypy, "lastrowid not maintained after " + # "connection close") @requirements.dbapi_lastrowid def test_native_lastrowid_autoinc(self): r = config.db.execute( -- cgit v1.2.1 From f6198d9abf453182f4b111e0579a7a4ef1614e79 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 12 Aug 2013 17:50:37 -0400 Subject: - A large refactoring of the ``sqlalchemy.sql`` package has reorganized the import structure of many core modules. ``sqlalchemy.schema`` and ``sqlalchemy.types`` remain in the top-level package, but are now just lists of names that pull from within ``sqlalchemy.sql``. Their implementations are now broken out among ``sqlalchemy.sql.type_api``, ``sqlalchemy.sql.sqltypes``, ``sqlalchemy.sql.schema`` and ``sqlalchemy.sql.ddl``, the last of which was moved from ``sqlalchemy.engine``. ``sqlalchemy.sql.expression`` is also a namespace now which pulls implementations mostly from ``sqlalchemy.sql.elements``, ``sqlalchemy.sql.selectable``, and ``sqlalchemy.sql.dml``. Most of the "factory" functions used to create SQL expression objects have been moved to classmethods or constructors, which are exposed in ``sqlalchemy.sql.expression`` using a programmatic system. Care has been taken such that all the original import namespaces remain intact and there should be no impact on any existing applications. The rationale here was to break out these very large modules into smaller ones, provide more manageable lists of function names, to greatly reduce "import cycles" and clarify the up-front importing of names, and to remove the need for redundant functions and documentation throughout the expression package. --- lib/sqlalchemy/testing/plugin/noseplugin.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/plugin/noseplugin.py b/lib/sqlalchemy/testing/plugin/noseplugin.py index b3cd3a4e3..319aefa96 100644 --- a/lib/sqlalchemy/testing/plugin/noseplugin.py +++ b/lib/sqlalchemy/testing/plugin/noseplugin.py @@ -351,6 +351,8 @@ class NoseSQLAlchemy(Plugin): return "" def wantFunction(self, fn): + if fn.__module__ is None: + return False if fn.__module__.startswith('sqlalchemy.testing'): return False -- cgit v1.2.1 From e9c748a7bf1acb1423efa92ad797e9a0fbcf1cbb Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 25 Aug 2013 17:37:59 -0400 Subject: - ensure rowcount is returned for an UPDATE with no implicit returning - modernize test for that - use py3k compatible next() in test_returning/test_versioning --- lib/sqlalchemy/testing/mock.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/mock.py b/lib/sqlalchemy/testing/mock.py index 650962384..fa2d477a7 100644 --- a/lib/sqlalchemy/testing/mock.py +++ b/lib/sqlalchemy/testing/mock.py @@ -4,10 +4,10 @@ from __future__ import absolute_import from ..util import py33 if py33: - from unittest.mock import MagicMock, Mock, call + from unittest.mock import MagicMock, Mock, call, patch else: try: - from mock import MagicMock, Mock, call + from mock import MagicMock, Mock, call, patch except ImportError: raise ImportError( "SQLAlchemy's test suite requires the " -- cgit v1.2.1 From 87b9f48c57bbbc75eb907509002e6a9687b85cdf Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 28 Aug 2013 00:04:38 -0400 Subject: - rework the profile thing to just rewrite all failing numbers when --write-profiles is set - some sqlite callcounts --- lib/sqlalchemy/testing/profiling.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/profiling.py b/lib/sqlalchemy/testing/profiling.py index bda44d80c..2e0a5babc 100644 --- a/lib/sqlalchemy/testing/profiling.py +++ b/lib/sqlalchemy/testing/profiling.py @@ -162,6 +162,15 @@ class ProfileStatsFile(object): per_platform['current_count'] += 1 return result + def replace(self, callcount): + test_key = _current_test + per_fn = self.data[test_key] + per_platform = per_fn[self.platform_key] + counts = per_platform['counts'] + counts[-1] = callcount + if self.write: + self._write() + def _header(self): return \ "# %s\n"\ @@ -263,16 +272,19 @@ def function_call_count(variance=0.05): if expected_count: deviance = int(callcount * variance) - if abs(callcount - expected_count) > deviance: + failed = abs(callcount - expected_count) > deviance + + if failed: + if _profile_stats.write: + _profile_stats.replace(callcount) + else: raise AssertionError( "Adjusted function call count %s not within %s%% " - "of expected %s. (Delete line %d of file %s to " - "regenerate this callcount, when tests are run " - "with --write-profiles.)" + "of expected %s. Rerun with --write-profiles to " + "regenerate this callcount." % ( callcount, (variance * 100), - expected_count, line_no, - _profile_stats.fname)) + expected_count)) return fn_result return update_wrapper(wrap, fn) return decorate -- cgit v1.2.1 From 03c9b2df770385fc3b2b0acbdcb809c2239b67ef Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 28 Aug 2013 10:19:11 -0400 Subject: - fix bug here in profiling.py - callcount --- lib/sqlalchemy/testing/profiling.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/profiling.py b/lib/sqlalchemy/testing/profiling.py index 2e0a5babc..4f6ea3f90 100644 --- a/lib/sqlalchemy/testing/profiling.py +++ b/lib/sqlalchemy/testing/profiling.py @@ -274,17 +274,17 @@ def function_call_count(variance=0.05): deviance = int(callcount * variance) failed = abs(callcount - expected_count) > deviance - if failed: - if _profile_stats.write: - _profile_stats.replace(callcount) - else: - raise AssertionError( - "Adjusted function call count %s not within %s%% " - "of expected %s. Rerun with --write-profiles to " - "regenerate this callcount." - % ( - callcount, (variance * 100), - expected_count)) + if failed: + if _profile_stats.write: + _profile_stats.replace(callcount) + else: + raise AssertionError( + "Adjusted function call count %s not within %s%% " + "of expected %s. Rerun with --write-profiles to " + "regenerate this callcount." + % ( + callcount, (variance * 100), + expected_count)) return fn_result return update_wrapper(wrap, fn) return decorate -- cgit v1.2.1 From 92534dc8f30d173deaa1221a6872fd9b7ceae325 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 14 Oct 2013 16:12:54 -0400 Subject: The MySQL :class:`.mysql.SET` type now features the same auto-quoting behavior as that of :class:`.mysql.ENUM`. Quotes are not required when setting up the value, but quotes that are present will be auto-detected along with a warning. This also helps with Alembic where the SET type doesn't render with quotes. [ticket:2817] --- lib/sqlalchemy/testing/__init__.py | 2 +- lib/sqlalchemy/testing/assertions.py | 48 ++++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 22 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/__init__.py b/lib/sqlalchemy/testing/__init__.py index a87829499..90512e41a 100644 --- a/lib/sqlalchemy/testing/__init__.py +++ b/lib/sqlalchemy/testing/__init__.py @@ -11,7 +11,7 @@ from .exclusions import db_spec, _is_excluded, fails_if, skip_if, future,\ from .assertions import emits_warning, emits_warning_on, uses_deprecated, \ eq_, ne_, is_, is_not_, startswith_, assert_raises, \ assert_raises_message, AssertsCompiledSQL, ComparesTables, \ - AssertsExecutionResults + AssertsExecutionResults, expect_deprecated from .util import run_as_contextmanager, rowset, fail, provide_metadata, adict diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index 96a8bc023..062fffb18 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -92,30 +92,36 @@ def uses_deprecated(*messages): @decorator def decorate(fn, *args, **kw): - # todo: should probably be strict about this, too - filters = [dict(action='ignore', - category=sa_exc.SAPendingDeprecationWarning)] - if not messages: - filters.append(dict(action='ignore', - category=sa_exc.SADeprecationWarning)) - else: - filters.extend( - [dict(action='ignore', - message=message, - category=sa_exc.SADeprecationWarning) - for message in - [(m.startswith('//') and - ('Call to deprecated function ' + m[2:]) or m) - for m in messages]]) - - for f in filters: - warnings.filterwarnings(**f) - try: + with expect_deprecated(*messages): return fn(*args, **kw) - finally: - resetwarnings() return decorate +@contextlib.contextmanager +def expect_deprecated(*messages): + # todo: should probably be strict about this, too + filters = [dict(action='ignore', + category=sa_exc.SAPendingDeprecationWarning)] + if not messages: + filters.append(dict(action='ignore', + category=sa_exc.SADeprecationWarning)) + else: + filters.extend( + [dict(action='ignore', + message=message, + category=sa_exc.SADeprecationWarning) + for message in + [(m.startswith('//') and + ('Call to deprecated function ' + m[2:]) or m) + for m in messages]]) + + for f in filters: + warnings.filterwarnings(**f) + try: + yield + finally: + resetwarnings() + + def global_cleanup_assertions(): """Check things that have to be finalized at the end of a test suite. -- cgit v1.2.1 From 4663ec98b226a7d495846f0d89c646110705bb30 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 20 Oct 2013 16:59:56 -0400 Subject: - The typing system now handles the task of rendering "literal bind" values, e.g. values that are normally bound parameters but due to context must be rendered as strings, typically within DDL constructs such as CHECK constraints and indexes (note that "literal bind" values become used by DDL as of :ticket:`2742`). A new method :meth:`.TypeEngine.literal_processor` serves as the base, and :meth:`.TypeDecorator.process_literal_param` is added to allow wrapping of a native literal rendering method. [ticket:2838] - enhance _get_colparams so that we can send flags like literal_binds into INSERT statements - add support in PG for inspecting standard_conforming_strings - add a new series of roundtrip tests based on INSERT of literal plus SELECT for basic literal rendering in dialect suite --- lib/sqlalchemy/testing/assertions.py | 11 +++- lib/sqlalchemy/testing/requirements.py | 9 +++ lib/sqlalchemy/testing/suite/test_types.py | 101 +++++++++++++++++++++++++++-- 3 files changed, 113 insertions(+), 8 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index 062fffb18..0d43d0e04 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -187,7 +187,8 @@ class AssertsCompiledSQL(object): checkparams=None, dialect=None, checkpositional=None, use_default_dialect=False, - allow_dialect_select=False): + allow_dialect_select=False, + literal_binds=False): if use_default_dialect: dialect = default.DefaultDialect() elif allow_dialect_select: @@ -205,14 +206,22 @@ class AssertsCompiledSQL(object): kw = {} + compile_kwargs = {} + if params is not None: kw['column_keys'] = list(params) + if literal_binds: + compile_kwargs['literal_binds'] = True + if isinstance(clause, orm.Query): context = clause._compile_context() context.statement.use_labels = True clause = context.statement + if compile_kwargs: + kw['compile_kwargs'] = compile_kwargs + c = clause.compile(dialect=dialect, **kw) param_str = repr(getattr(c, 'params', {})) diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py index d301dc69f..7dc6ea40b 100644 --- a/lib/sqlalchemy/testing/requirements.py +++ b/lib/sqlalchemy/testing/requirements.py @@ -295,6 +295,15 @@ class SuiteRequirements(Requirements): """Target driver must support some degree of non-ascii symbol names.""" return exclusions.closed() + @property + def datetime_literals(self): + """target dialect supports rendering of a date, time, or datetime as a + literal string, e.g. via the TypeEngine.literal_processor() method. + + """ + + return exclusions.closed() + @property def datetime(self): """target dialect supports representation of Python diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py index 0de462eb7..5523523aa 100644 --- a/lib/sqlalchemy/testing/suite/test_types.py +++ b/lib/sqlalchemy/testing/suite/test_types.py @@ -5,7 +5,7 @@ from ..assertions import eq_ from ..config import requirements from sqlalchemy import Integer, Unicode, UnicodeText, select from sqlalchemy import Date, DateTime, Time, MetaData, String, \ - Text, Numeric, Float + Text, Numeric, Float, literal from ..schema import Table, Column from ... import testing import decimal @@ -13,7 +13,31 @@ import datetime from ...util import u from ... import util -class _UnicodeFixture(object): + +class _LiteralRoundTripFixture(object): + @testing.provide_metadata + def _literal_round_trip(self, type_, input_, output): + """test literal rendering """ + + # for literal, we test the literal render in an INSERT + # into a typed column. we can then SELECT it back as it's + # official type; ideally we'd be able to use CAST here + # but MySQL in particular can't CAST fully + t = Table('t', self.metadata, Column('x', type_)) + t.create() + + for value in input_: + ins = t.insert().values(x=literal(value)).compile( + dialect=testing.db.dialect, + compile_kwargs=dict(literal_binds=True) + ) + testing.db.execute(ins) + + for row in t.select().execute(): + assert row[0] in output + + +class _UnicodeFixture(_LiteralRoundTripFixture): __requires__ = 'unicode_data', data = u("Alors vous imaginez ma surprise, au lever du jour, "\ @@ -87,6 +111,9 @@ class _UnicodeFixture(object): ).first() eq_(row, (u(''),)) + def test_literal(self): + self._literal_round_trip(self.datatype, [self.data], [self.data]) + class UnicodeVarcharTest(_UnicodeFixture, fixtures.TablesTest): __requires__ = 'unicode_data', @@ -107,7 +134,7 @@ class UnicodeTextTest(_UnicodeFixture, fixtures.TablesTest): def test_empty_strings_text(self): self._test_empty_strings() -class TextTest(fixtures.TablesTest): +class TextTest(_LiteralRoundTripFixture, fixtures.TablesTest): @classmethod def define_tables(cls, metadata): Table('text_table', metadata, @@ -140,8 +167,18 @@ class TextTest(fixtures.TablesTest): ).first() eq_(row, ('',)) + def test_literal(self): + self._literal_round_trip(Text, ["some text"], ["some text"]) + + def test_literal_quoting(self): + data = '''some 'text' hey "hi there" that's text''' + self._literal_round_trip(Text, [data], [data]) + + def test_literal_backslashes(self): + data = r'backslash one \ backslash two \\ end' + self._literal_round_trip(Text, [data], [data]) -class StringTest(fixtures.TestBase): +class StringTest(_LiteralRoundTripFixture, fixtures.TestBase): @requirements.unbounded_varchar def test_nolength_string(self): metadata = MetaData() @@ -152,8 +189,19 @@ class StringTest(fixtures.TestBase): foo.create(config.db) foo.drop(config.db) + def test_literal(self): + self._literal_round_trip(String(40), ["some text"], ["some text"]) -class _DateFixture(object): + def test_literal_quoting(self): + data = '''some 'text' hey "hi there" that's text''' + self._literal_round_trip(String(40), [data], [data]) + + def test_literal_backslashes(self): + data = r'backslash one \ backslash two \\ end' + self._literal_round_trip(Text, [data], [data]) + + +class _DateFixture(_LiteralRoundTripFixture): compare = None @classmethod @@ -198,6 +246,12 @@ class _DateFixture(object): ).first() eq_(row, (None,)) + @testing.requires.datetime_literals + def test_literal(self): + compare = self.compare or self.data + self._literal_round_trip(self.datatype, [self.data], [compare]) + + class DateTimeTest(_DateFixture, fixtures.TablesTest): __requires__ = 'datetime', @@ -247,7 +301,12 @@ class DateHistoricTest(_DateFixture, fixtures.TablesTest): datatype = Date data = datetime.date(1727, 4, 1) -class NumericTest(fixtures.TestBase): + +class IntegerTest(_LiteralRoundTripFixture, fixtures.TestBase): + def test_literal(self): + self._literal_round_trip(Integer, [5], [5]) + +class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase): @testing.emits_warning(r".*does \*not\* support Decimal objects natively") @testing.provide_metadata @@ -269,6 +328,30 @@ class NumericTest(fixtures.TestBase): [str(x) for x in output], ) + + @testing.emits_warning(r".*does \*not\* support Decimal objects natively") + def test_render_literal_numeric(self): + self._literal_round_trip( + Numeric(precision=8, scale=4), + [15.7563, decimal.Decimal("15.7563")], + [decimal.Decimal("15.7563")], + ) + + @testing.emits_warning(r".*does \*not\* support Decimal objects natively") + def test_render_literal_numeric_asfloat(self): + self._literal_round_trip( + Numeric(precision=8, scale=4, asdecimal=False), + [15.7563, decimal.Decimal("15.7563")], + [15.7563], + ) + + def test_render_literal_float(self): + self._literal_round_trip( + Float(4), + [15.7563, decimal.Decimal("15.7563")], + [15.7563], + ) + def test_numeric_as_decimal(self): self._do_test( Numeric(precision=8, scale=4), @@ -291,6 +374,7 @@ class NumericTest(fixtures.TestBase): [decimal.Decimal("15.7563"), None], ) + def test_float_as_float(self): self._do_test( Float(precision=8), @@ -299,6 +383,7 @@ class NumericTest(fixtures.TestBase): filter_=lambda n: n is not None and round(n, 5) or None ) + @testing.requires.precision_numerics_general def test_precision_decimal(self): numbers = set([ @@ -313,6 +398,7 @@ class NumericTest(fixtures.TestBase): numbers, ) + @testing.requires.precision_numerics_enotation_large def test_enotation_decimal(self): """test exceedingly small decimals. @@ -342,6 +428,7 @@ class NumericTest(fixtures.TestBase): numbers ) + @testing.requires.precision_numerics_enotation_large def test_enotation_decimal_large(self): """test exceedingly large decimals. @@ -389,7 +476,7 @@ class NumericTest(fixtures.TestBase): __all__ = ('UnicodeVarcharTest', 'UnicodeTextTest', 'DateTest', 'DateTimeTest', 'TextTest', - 'NumericTest', + 'NumericTest', 'IntegerTest', 'DateTimeHistoricTest', 'DateTimeCoercedToDateTimeTest', 'TimeMicrosecondsTest', 'TimeTest', 'DateTimeMicrosecondsTest', 'DateHistoricTest', 'StringTest') -- cgit v1.2.1 From 5d5700c40e0abc6c228c03c6261bdc6627a3e02a Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 21 Oct 2013 23:21:11 -0400 Subject: - oursql returns a pure FP here which isn't exact --- lib/sqlalchemy/testing/suite/test_types.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py index 5523523aa..d04829a79 100644 --- a/lib/sqlalchemy/testing/suite/test_types.py +++ b/lib/sqlalchemy/testing/suite/test_types.py @@ -345,11 +345,12 @@ class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase): [15.7563], ) + @testing.requires.floats_to_four_decimals def test_render_literal_float(self): self._literal_round_trip( Float(4), [15.7563, decimal.Decimal("15.7563")], - [15.7563], + [15.7563,], ) def test_numeric_as_decimal(self): -- cgit v1.2.1 From 15f781cc3defb02ff799c409492156e10b675534 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 21 Oct 2013 23:26:08 -0400 Subject: - use a different approach here since oracle isn't doing it either, just round it --- lib/sqlalchemy/testing/suite/test_types.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py index d04829a79..3eb105ba3 100644 --- a/lib/sqlalchemy/testing/suite/test_types.py +++ b/lib/sqlalchemy/testing/suite/test_types.py @@ -16,7 +16,7 @@ from ... import util class _LiteralRoundTripFixture(object): @testing.provide_metadata - def _literal_round_trip(self, type_, input_, output): + def _literal_round_trip(self, type_, input_, output, filter_=None): """test literal rendering """ # for literal, we test the literal render in an INSERT @@ -34,7 +34,10 @@ class _LiteralRoundTripFixture(object): testing.db.execute(ins) for row in t.select().execute(): - assert row[0] in output + value = row[0] + if filter_ is not None: + value = filter_(value) + assert value in output class _UnicodeFixture(_LiteralRoundTripFixture): @@ -345,12 +348,12 @@ class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase): [15.7563], ) - @testing.requires.floats_to_four_decimals def test_render_literal_float(self): self._literal_round_trip( Float(4), [15.7563, decimal.Decimal("15.7563")], [15.7563,], + filter_=lambda n: n is not None and round(n, 5) or None ) def test_numeric_as_decimal(self): -- cgit v1.2.1 From 42f2a16be7ff462048857799decc41a95c459fc3 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 26 Oct 2013 16:32:17 -0400 Subject: - add copyright to source files missing it --- lib/sqlalchemy/testing/__init__.py | 5 +++++ lib/sqlalchemy/testing/assertions.py | 6 ++++++ lib/sqlalchemy/testing/assertsql.py | 5 +++++ lib/sqlalchemy/testing/config.py | 6 ++++++ lib/sqlalchemy/testing/engines.py | 8 +++++++- lib/sqlalchemy/testing/entities.py | 6 ++++++ lib/sqlalchemy/testing/exclusions.py | 5 +++++ lib/sqlalchemy/testing/fixtures.py | 6 ++++++ lib/sqlalchemy/testing/mock.py | 6 ++++++ lib/sqlalchemy/testing/pickleable.py | 6 ++++++ lib/sqlalchemy/testing/plugin/noseplugin.py | 6 ++++++ lib/sqlalchemy/testing/profiling.py | 6 ++++++ lib/sqlalchemy/testing/requirements.py | 6 ++++++ lib/sqlalchemy/testing/runner.py | 5 +++++ lib/sqlalchemy/testing/schema.py | 5 +++++ lib/sqlalchemy/testing/util.py | 6 ++++++ lib/sqlalchemy/testing/warnings.py | 6 ++++++ 17 files changed, 98 insertions(+), 1 deletion(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/__init__.py b/lib/sqlalchemy/testing/__init__.py index 90512e41a..34439fd20 100644 --- a/lib/sqlalchemy/testing/__init__.py +++ b/lib/sqlalchemy/testing/__init__.py @@ -1,3 +1,8 @@ +# testing/__init__.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php from .warnings import testing_warn, assert_warnings, resetwarnings diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index 0d43d0e04..8a859c0b1 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -1,3 +1,9 @@ +# testing/assertions.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + from __future__ import absolute_import from . import util as testutil diff --git a/lib/sqlalchemy/testing/assertsql.py b/lib/sqlalchemy/testing/assertsql.py index a6b63b2c3..d7683250d 100644 --- a/lib/sqlalchemy/testing/assertsql.py +++ b/lib/sqlalchemy/testing/assertsql.py @@ -1,3 +1,8 @@ +# testing/assertsql.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php from ..engine.default import DefaultDialect from .. import util diff --git a/lib/sqlalchemy/testing/config.py b/lib/sqlalchemy/testing/config.py index ae4f585e1..9bee17d10 100644 --- a/lib/sqlalchemy/testing/config.py +++ b/lib/sqlalchemy/testing/config.py @@ -1,2 +1,8 @@ +# testing/config.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + requirements = None db = None diff --git a/lib/sqlalchemy/testing/engines.py b/lib/sqlalchemy/testing/engines.py index 29c8b6a03..11392c7e2 100644 --- a/lib/sqlalchemy/testing/engines.py +++ b/lib/sqlalchemy/testing/engines.py @@ -1,3 +1,9 @@ +# testing/engines.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + from __future__ import absolute_import import types @@ -75,7 +81,7 @@ class ConnectionKiller(object): for conn, rec in self.conns: self._safe(conn.close) rec.connection = None - + self.conns = set() for rec in list(self.testing_engines): rec.dispose() diff --git a/lib/sqlalchemy/testing/entities.py b/lib/sqlalchemy/testing/entities.py index c0dd58650..26203a403 100644 --- a/lib/sqlalchemy/testing/entities.py +++ b/lib/sqlalchemy/testing/entities.py @@ -1,3 +1,9 @@ +# testing/entities.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + import sqlalchemy as sa from sqlalchemy import exc as sa_exc diff --git a/lib/sqlalchemy/testing/exclusions.py b/lib/sqlalchemy/testing/exclusions.py index f580f3fde..d126c3aa5 100644 --- a/lib/sqlalchemy/testing/exclusions.py +++ b/lib/sqlalchemy/testing/exclusions.py @@ -1,3 +1,8 @@ +# testing/exclusions.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php import operator diff --git a/lib/sqlalchemy/testing/fixtures.py b/lib/sqlalchemy/testing/fixtures.py index daa779ae3..a1c9cebee 100644 --- a/lib/sqlalchemy/testing/fixtures.py +++ b/lib/sqlalchemy/testing/fixtures.py @@ -1,3 +1,9 @@ +# testing/fixtures.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + from . import config from . import assertions, schema from .util import adict diff --git a/lib/sqlalchemy/testing/mock.py b/lib/sqlalchemy/testing/mock.py index fa2d477a7..ec88eaafe 100644 --- a/lib/sqlalchemy/testing/mock.py +++ b/lib/sqlalchemy/testing/mock.py @@ -1,3 +1,9 @@ +# testing/mock.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + """Import stub for mock library. """ from __future__ import absolute_import diff --git a/lib/sqlalchemy/testing/pickleable.py b/lib/sqlalchemy/testing/pickleable.py index 09d51b5fa..0224b89d2 100644 --- a/lib/sqlalchemy/testing/pickleable.py +++ b/lib/sqlalchemy/testing/pickleable.py @@ -1,3 +1,9 @@ +# testing/pickleable.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + """Classes used in pickling tests, need to be at the module level for unpickling. """ diff --git a/lib/sqlalchemy/testing/plugin/noseplugin.py b/lib/sqlalchemy/testing/plugin/noseplugin.py index 319aefa96..704e90d53 100644 --- a/lib/sqlalchemy/testing/plugin/noseplugin.py +++ b/lib/sqlalchemy/testing/plugin/noseplugin.py @@ -1,3 +1,9 @@ +# plugin/noseplugin.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + """Enhance nose with extra options and behaviors for running SQLAlchemy tests. When running ./sqla_nose.py, this module is imported relative to the diff --git a/lib/sqlalchemy/testing/profiling.py b/lib/sqlalchemy/testing/profiling.py index 4f6ea3f90..8d3d81c8e 100644 --- a/lib/sqlalchemy/testing/profiling.py +++ b/lib/sqlalchemy/testing/profiling.py @@ -1,3 +1,9 @@ +# testing/profiling.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + """Profiling support for unit and performance tests. These are special purpose profiling methods which operate diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py index 7dc6ea40b..408c3705e 100644 --- a/lib/sqlalchemy/testing/requirements.py +++ b/lib/sqlalchemy/testing/requirements.py @@ -1,3 +1,9 @@ +# testing/requirements.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + """Global database feature support policy. Provides decorators to mark tests requiring specific feature support from the diff --git a/lib/sqlalchemy/testing/runner.py b/lib/sqlalchemy/testing/runner.py index 2bdbaebd1..67e7fddc1 100644 --- a/lib/sqlalchemy/testing/runner.py +++ b/lib/sqlalchemy/testing/runner.py @@ -1,4 +1,9 @@ #!/usr/bin/env python +# testing/runner.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php """ Nose test runner module. diff --git a/lib/sqlalchemy/testing/schema.py b/lib/sqlalchemy/testing/schema.py index 025bbaabe..93dddc5a7 100644 --- a/lib/sqlalchemy/testing/schema.py +++ b/lib/sqlalchemy/testing/schema.py @@ -1,3 +1,8 @@ +# testing/schema.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php from . import exclusions from .. import schema, event diff --git a/lib/sqlalchemy/testing/util.py b/lib/sqlalchemy/testing/util.py index 1288902f2..da6e70eee 100644 --- a/lib/sqlalchemy/testing/util.py +++ b/lib/sqlalchemy/testing/util.py @@ -1,3 +1,9 @@ +# testing/util.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + from ..util import jython, pypy, defaultdict, decorator, py2k import decimal import gc diff --git a/lib/sqlalchemy/testing/warnings.py b/lib/sqlalchemy/testing/warnings.py index 6193acd88..abc33f60b 100644 --- a/lib/sqlalchemy/testing/warnings.py +++ b/lib/sqlalchemy/testing/warnings.py @@ -1,3 +1,9 @@ +# testing/warnings.py +# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + from __future__ import absolute_import import warnings -- cgit v1.2.1 From 2aa00c49d7a1a783ff50832f2de7760bfaaccf6d Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 21 Nov 2013 13:30:32 -0500 Subject: - Fixed bug which prevented the ``serializer`` extension from working correctly with table or column names that contain non-ASCII characters. [ticket:2869] --- lib/sqlalchemy/testing/assertions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index 8a859c0b1..ebd1b424d 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -235,7 +235,7 @@ class AssertsCompiledSQL(object): if util.py3k: param_str = param_str.encode('utf-8').decode('ascii', 'ignore') - print("\nSQL String:\n" + util.text_type(c) + param_str) + print("\nSQL String:\n" + util.text_type(c).encode('utf-8') + param_str) cc = re.sub(r'[\n\t]', '', util.text_type(c)) -- cgit v1.2.1 From 5cdb5f1403e63493643b42fcebe65badce484065 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 21 Nov 2013 13:38:45 -0500 Subject: adjustment to work on py3k as well --- lib/sqlalchemy/testing/assertions.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index ebd1b424d..ce3a292ac 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -234,8 +234,10 @@ class AssertsCompiledSQL(object): if util.py3k: param_str = param_str.encode('utf-8').decode('ascii', 'ignore') + print(("\nSQL String:\n" + util.text_type(c) + param_str).encode('utf-8')) + else: + print("\nSQL String:\n" + util.text_type(c).encode('utf-8') + param_str) - print("\nSQL String:\n" + util.text_type(c).encode('utf-8') + param_str) cc = re.sub(r'[\n\t]', '', util.text_type(c)) -- cgit v1.2.1 From 6b79d2ea7951abc2bb6083b541db0fbf71590dd3 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 22 Nov 2013 20:04:19 -0500 Subject: - The precision used when coercing a returned floating point value to Python ``Decimal`` via string is now configurable. The flag ``decimal_return_scale`` is now supported by all :class:`.Numeric` and :class:`.Float` types, which will ensure this many digits are taken from the native floating point value when it is converted to string. If not present, the type will make use of the value of ``.scale``, if the type supports this setting and it is non-None. Otherwise the original default length of 10 is used. [ticket:2867] --- lib/sqlalchemy/testing/requirements.py | 8 ++++++++ lib/sqlalchemy/testing/suite/test_types.py | 10 ++++++++++ 2 files changed, 18 insertions(+) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py index 408c3705e..e48fa2c00 100644 --- a/lib/sqlalchemy/testing/requirements.py +++ b/lib/sqlalchemy/testing/requirements.py @@ -393,6 +393,14 @@ class SuiteRequirements(Requirements): return exclusions.closed() + @property + def precision_generic_float_type(self): + """target backend will return native floating point numbers with at + least seven decimal places when using the generic Float type. + + """ + return exclusions.open() + @property def floats_to_four_decimals(self): """target backend can return a floating-point number with four diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py index 3eb105ba3..b147f891a 100644 --- a/lib/sqlalchemy/testing/suite/test_types.py +++ b/lib/sqlalchemy/testing/suite/test_types.py @@ -356,6 +356,16 @@ class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase): filter_=lambda n: n is not None and round(n, 5) or None ) + + @testing.requires.precision_generic_float_type + def test_float_custom_scale(self): + self._do_test( + Float(None, decimal_return_scale=7, asdecimal=True), + [15.7563827, decimal.Decimal("15.7563827")], + [decimal.Decimal("15.7563827"),], + check_scale=True + ) + def test_numeric_as_decimal(self): self._do_test( Numeric(precision=8, scale=4), -- cgit v1.2.1 From 31cecebd4831fbf58310509c1486244a532d96b9 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 28 Nov 2013 23:23:27 -0500 Subject: - add support for specifying tables or entities for "of" - implement Query with_for_update() - rework docs and tests --- lib/sqlalchemy/testing/assertions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index ce3a292ac..0e12963ce 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -8,7 +8,7 @@ from __future__ import absolute_import from . import util as testutil from sqlalchemy import pool, orm, util -from sqlalchemy.engine import default, create_engine +from sqlalchemy.engine import default, create_engine, url from sqlalchemy import exc as sa_exc from sqlalchemy.util import decorator from sqlalchemy import types as sqltypes, schema @@ -208,7 +208,7 @@ class AssertsCompiledSQL(object): elif dialect == 'default': dialect = default.DefaultDialect() elif isinstance(dialect, util.string_types): - dialect = create_engine("%s://" % dialect).dialect + dialect = url.URL(dialect).get_dialect()() kw = {} -- cgit v1.2.1 From 10ac89cef3dafc7a23c8947255f26d60db2c4d84 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 17 Dec 2013 14:24:48 -0500 Subject: - enhance the exclusions system to support database versions within the __only_on__ attribute --- lib/sqlalchemy/testing/exclusions.py | 9 ++++++++- lib/sqlalchemy/testing/plugin/noseplugin.py | 15 +++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/exclusions.py b/lib/sqlalchemy/testing/exclusions.py index d126c3aa5..9f14ee105 100644 --- a/lib/sqlalchemy/testing/exclusions.py +++ b/lib/sqlalchemy/testing/exclusions.py @@ -98,7 +98,14 @@ class Predicate(object): elif isinstance(predicate, tuple): return SpecPredicate(*predicate) elif isinstance(predicate, util.string_types): - return SpecPredicate(predicate, None, None) + tokens = predicate.split(" ", 2) + op = spec = None + db = tokens.pop(0) + if tokens: + op = tokens.pop(0) + if tokens: + spec = tuple(int(d) for d in tokens.pop(0).split(".")) + return SpecPredicate(db, op, spec) elif util.callable(predicate): return LambdaPredicate(predicate) else: diff --git a/lib/sqlalchemy/testing/plugin/noseplugin.py b/lib/sqlalchemy/testing/plugin/noseplugin.py index 704e90d53..b55ba4fc0 100644 --- a/lib/sqlalchemy/testing/plugin/noseplugin.py +++ b/lib/sqlalchemy/testing/plugin/noseplugin.py @@ -393,8 +393,9 @@ class NoseSQLAlchemy(Plugin): check.reason if check.reason else ( - "'%s' unsupported on DB implementation '%s'" % ( - cls.__name__, config.db.name + "'%s' unsupported on DB implementation '%s' == %s" % ( + cls.__name__, config.db.name, + config.db.dialect.server_version_info ) ) ) @@ -403,16 +404,18 @@ class NoseSQLAlchemy(Plugin): spec = exclusions.db_spec(*cls.__unsupported_on__) if spec(config.db): raise SkipTest( - "'%s' unsupported on DB implementation '%s'" % ( - cls.__name__, config.db.name) + "'%s' unsupported on DB implementation '%s' == %s" % ( + cls.__name__, config.db.name, + config.db.dialect.server_version_info) ) if getattr(cls, '__only_on__', None): spec = exclusions.db_spec(*util.to_list(cls.__only_on__)) if not spec(config.db): raise SkipTest( - "'%s' unsupported on DB implementation '%s'" % ( - cls.__name__, config.db.name) + "'%s' unsupported on DB implementation '%s' == %s" % ( + cls.__name__, config.db.name, + config.db.dialect.server_version_info) ) if getattr(cls, '__skip_if__', False): -- cgit v1.2.1 From 0cba61d150b84646f8da02cff66e25e9542f92a6 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 27 Dec 2013 13:05:32 -0500 Subject: - repair some suite tests for firebird --- lib/sqlalchemy/testing/requirements.py | 14 ++++++++++++++ lib/sqlalchemy/testing/suite/test_insert.py | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py index e48fa2c00..3e48ba026 100644 --- a/lib/sqlalchemy/testing/requirements.py +++ b/lib/sqlalchemy/testing/requirements.py @@ -138,6 +138,20 @@ class SuiteRequirements(Requirements): return exclusions.open() + @property + def fetch_rows_post_commit(self): + """target platform will allow cursor.fetchone() to proceed after a + COMMIT. + + Typically this refers to an INSERT statement with RETURNING which + is invoked within "autocommit". If the row can be returned + after the autocommit, then this rule can be open. + + """ + + return exclusions.open() + + @property def empty_inserts(self): """target platform supports INSERT with no values, i.e. diff --git a/lib/sqlalchemy/testing/suite/test_insert.py b/lib/sqlalchemy/testing/suite/test_insert.py index 21141f244..deda63b24 100644 --- a/lib/sqlalchemy/testing/suite/test_insert.py +++ b/lib/sqlalchemy/testing/suite/test_insert.py @@ -172,7 +172,8 @@ class ReturningTest(fixtures.TablesTest): Column('data', String(50)) ) - def test_explicit_returning_pk(self): + @requirements.fetch_rows_post_commit + def test_explicit_returning_pk_autocommit(self): engine = config.db table = self.tables.autoinc_pk r = engine.execute( @@ -184,6 +185,19 @@ class ReturningTest(fixtures.TablesTest): fetched_pk = config.db.scalar(select([table.c.id])) eq_(fetched_pk, pk) + def test_explicit_returning_pk_no_autocommit(self): + engine = config.db + table = self.tables.autoinc_pk + with engine.begin() as conn: + r = conn.execute( + table.insert().returning( + table.c.id), + data="some data" + ) + pk = r.first()[0] + fetched_pk = config.db.scalar(select([table.c.id])) + eq_(fetched_pk, pk) + def test_autoincrement_on_insert_implcit_returning(self): config.db.execute( -- cgit v1.2.1 From a51c41e6305c3fcd64bdb10f8b769acad8a7cbdc Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 27 Dec 2013 13:28:18 -0500 Subject: - add a test which creates tables and views at the same time, then tests that the lists of each can be reflected independently. Testing [ticket:2898] at the moment. --- lib/sqlalchemy/testing/suite/test_reflection.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/suite/test_reflection.py b/lib/sqlalchemy/testing/suite/test_reflection.py index 5a8a54c46..228bf44ce 100644 --- a/lib/sqlalchemy/testing/suite/test_reflection.py +++ b/lib/sqlalchemy/testing/suite/test_reflection.py @@ -180,6 +180,12 @@ class ComponentReflectionTest(fixtures.TablesTest): def test_get_view_names_with_schema(self): self._test_get_table_names('test_schema', table_type='view') + @testing.requires.table_reflection + @testing.requires.view_reflection + def test_get_tables_and_views(self): + self._test_get_table_names() + self._test_get_table_names(table_type='view') + def _test_get_columns(self, schema=None, table_type='table'): meta = MetaData(testing.db) users, addresses, dingalings = self.tables.users, \ -- cgit v1.2.1 From aeb5ffec2820489eb607e1514135b80475fff8a1 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 27 Dec 2013 16:37:57 -0500 Subject: - actually check the list of views! --- lib/sqlalchemy/testing/suite/test_reflection.py | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/suite/test_reflection.py b/lib/sqlalchemy/testing/suite/test_reflection.py index 228bf44ce..b30f32cff 100644 --- a/lib/sqlalchemy/testing/suite/test_reflection.py +++ b/lib/sqlalchemy/testing/suite/test_reflection.py @@ -147,6 +147,7 @@ class ComponentReflectionTest(fixtures.TablesTest): table_names = insp.get_view_names(schema) table_names.sort() answer = ['email_addresses_v', 'users_v'] + eq_(sorted(table_names), answer) else: table_names = insp.get_table_names(schema, order_by=order_by) -- cgit v1.2.1 From d8bc6673c0bb34258bf4c54699ceede777664600 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 28 Dec 2013 16:37:22 -0500 Subject: - fix the insert from select test to use a non-autoinc table --- lib/sqlalchemy/testing/suite/test_insert.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/suite/test_insert.py b/lib/sqlalchemy/testing/suite/test_insert.py index deda63b24..5732e37ec 100644 --- a/lib/sqlalchemy/testing/suite/test_insert.py +++ b/lib/sqlalchemy/testing/suite/test_insert.py @@ -82,6 +82,10 @@ class InsertBehaviorTest(fixtures.TablesTest): test_needs_autoincrement=True), Column('data', String(50)) ) + Table('manual_pk', metadata, + Column('id', Integer, primary_key=True, autoincrement=False), + Column('data', String(50)) + ) def test_autoclose_on_insert(self): if requirements.returning.enabled: @@ -124,13 +128,13 @@ class InsertBehaviorTest(fixtures.TablesTest): @requirements.insert_from_select def test_insert_from_select(self): - table = self.tables.autoinc_pk + table = self.tables.manual_pk config.db.execute( table.insert(), [ - dict(data="data1"), - dict(data="data2"), - dict(data="data3"), + dict(id=1, data="data1"), + dict(id=2, data="data2"), + dict(id=3, data="data3"), ] ) -- cgit v1.2.1 From 1eb92e50d9845642940e7ab20906384bebec85fb Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 28 Dec 2013 17:50:19 -0500 Subject: - apply a similar fix for floats to mssql+pyodbc as we did to firebird - wrangle through osx+pyodbc+freetds to get at least test_suite to pass again with mssql+pyodbc. invovled adding some silly requirements --- lib/sqlalchemy/testing/requirements.py | 10 ++++++++++ lib/sqlalchemy/testing/suite/test_types.py | 24 ++++++++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py index 3e48ba026..60e966b3b 100644 --- a/lib/sqlalchemy/testing/requirements.py +++ b/lib/sqlalchemy/testing/requirements.py @@ -424,6 +424,16 @@ class SuiteRequirements(Requirements): """ return exclusions.open() + @property + def fetch_null_from_numeric(self): + """target backend doesn't crash when you try to select a NUMERIC + value that has a value of NULL. + + Added to support Pyodbc bug #351. + """ + + return exclusions.open() + @property def text_type(self): """Target database must support an unbounded Text() " diff --git a/lib/sqlalchemy/testing/suite/test_types.py b/lib/sqlalchemy/testing/suite/test_types.py index b147f891a..a6e937e8e 100644 --- a/lib/sqlalchemy/testing/suite/test_types.py +++ b/lib/sqlalchemy/testing/suite/test_types.py @@ -369,15 +369,31 @@ class NumericTest(_LiteralRoundTripFixture, fixtures.TestBase): def test_numeric_as_decimal(self): self._do_test( Numeric(precision=8, scale=4), - [15.7563, decimal.Decimal("15.7563"), None], - [decimal.Decimal("15.7563"), None], + [15.7563, decimal.Decimal("15.7563")], + [decimal.Decimal("15.7563")], ) def test_numeric_as_float(self): self._do_test( Numeric(precision=8, scale=4, asdecimal=False), - [15.7563, decimal.Decimal("15.7563"), None], - [15.7563, None], + [15.7563, decimal.Decimal("15.7563")], + [15.7563], + ) + + @testing.requires.fetch_null_from_numeric + def test_numeric_null_as_decimal(self): + self._do_test( + Numeric(precision=8, scale=4), + [None], + [None], + ) + + @testing.requires.fetch_null_from_numeric + def test_numeric_null_as_float(self): + self._do_test( + Numeric(precision=8, scale=4, asdecimal=False), + [None], + [None], ) @testing.requires.floats_to_four_decimals -- cgit v1.2.1 From 4b923d37bdfdb44d9a3e74aed08e2726e14c3b19 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 2 Jan 2014 14:23:14 -0500 Subject: - support addition of fails_if()/only_on(), just wraps the decorators - update a few exclusions to support current pymssql. passes all of test_suite and dialect/mssql --- lib/sqlalchemy/testing/exclusions.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/exclusions.py b/lib/sqlalchemy/testing/exclusions.py index 9f14ee105..611e9de6c 100644 --- a/lib/sqlalchemy/testing/exclusions.py +++ b/lib/sqlalchemy/testing/exclusions.py @@ -24,6 +24,11 @@ class skip_if(object): def enabled(self): return not self.predicate() + def __add__(self, other): + def decorate(fn): + return other(self(fn)) + return decorate + @contextlib.contextmanager def fail_if(self, name='block'): try: -- cgit v1.2.1 From f89d4d216bd7605c920b7b8a10ecde6bfea2238c Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sun, 5 Jan 2014 16:57:05 -0500 Subject: - happy new year --- lib/sqlalchemy/testing/__init__.py | 2 +- lib/sqlalchemy/testing/assertions.py | 2 +- lib/sqlalchemy/testing/assertsql.py | 2 +- lib/sqlalchemy/testing/config.py | 2 +- lib/sqlalchemy/testing/engines.py | 2 +- lib/sqlalchemy/testing/entities.py | 2 +- lib/sqlalchemy/testing/exclusions.py | 2 +- lib/sqlalchemy/testing/fixtures.py | 2 +- lib/sqlalchemy/testing/mock.py | 2 +- lib/sqlalchemy/testing/pickleable.py | 2 +- lib/sqlalchemy/testing/plugin/noseplugin.py | 2 +- lib/sqlalchemy/testing/profiling.py | 2 +- lib/sqlalchemy/testing/requirements.py | 2 +- lib/sqlalchemy/testing/runner.py | 2 +- lib/sqlalchemy/testing/schema.py | 2 +- lib/sqlalchemy/testing/util.py | 2 +- lib/sqlalchemy/testing/warnings.py | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/__init__.py b/lib/sqlalchemy/testing/__init__.py index 34439fd20..8ad856e2b 100644 --- a/lib/sqlalchemy/testing/__init__.py +++ b/lib/sqlalchemy/testing/__init__.py @@ -1,5 +1,5 @@ # testing/__init__.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index 0e12963ce..61649e5e3 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -1,5 +1,5 @@ # testing/assertions.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/assertsql.py b/lib/sqlalchemy/testing/assertsql.py index d7683250d..3e0d4c9d3 100644 --- a/lib/sqlalchemy/testing/assertsql.py +++ b/lib/sqlalchemy/testing/assertsql.py @@ -1,5 +1,5 @@ # testing/assertsql.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/config.py b/lib/sqlalchemy/testing/config.py index 9bee17d10..64f578dab 100644 --- a/lib/sqlalchemy/testing/config.py +++ b/lib/sqlalchemy/testing/config.py @@ -1,5 +1,5 @@ # testing/config.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/engines.py b/lib/sqlalchemy/testing/engines.py index 11392c7e2..d240645a8 100644 --- a/lib/sqlalchemy/testing/engines.py +++ b/lib/sqlalchemy/testing/engines.py @@ -1,5 +1,5 @@ # testing/engines.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/entities.py b/lib/sqlalchemy/testing/entities.py index 26203a403..0553e0e22 100644 --- a/lib/sqlalchemy/testing/entities.py +++ b/lib/sqlalchemy/testing/entities.py @@ -1,5 +1,5 @@ # testing/entities.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/exclusions.py b/lib/sqlalchemy/testing/exclusions.py index 611e9de6c..f868f6396 100644 --- a/lib/sqlalchemy/testing/exclusions.py +++ b/lib/sqlalchemy/testing/exclusions.py @@ -1,5 +1,5 @@ # testing/exclusions.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/fixtures.py b/lib/sqlalchemy/testing/fixtures.py index a1c9cebee..464a723d2 100644 --- a/lib/sqlalchemy/testing/fixtures.py +++ b/lib/sqlalchemy/testing/fixtures.py @@ -1,5 +1,5 @@ # testing/fixtures.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/mock.py b/lib/sqlalchemy/testing/mock.py index ec88eaafe..18ba053ea 100644 --- a/lib/sqlalchemy/testing/mock.py +++ b/lib/sqlalchemy/testing/mock.py @@ -1,5 +1,5 @@ # testing/mock.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/pickleable.py b/lib/sqlalchemy/testing/pickleable.py index 0224b89d2..9a41034bf 100644 --- a/lib/sqlalchemy/testing/pickleable.py +++ b/lib/sqlalchemy/testing/pickleable.py @@ -1,5 +1,5 @@ # testing/pickleable.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/plugin/noseplugin.py b/lib/sqlalchemy/testing/plugin/noseplugin.py index b55ba4fc0..27a028cd4 100644 --- a/lib/sqlalchemy/testing/plugin/noseplugin.py +++ b/lib/sqlalchemy/testing/plugin/noseplugin.py @@ -1,5 +1,5 @@ # plugin/noseplugin.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/profiling.py b/lib/sqlalchemy/testing/profiling.py index 8d3d81c8e..8f5f3f70a 100644 --- a/lib/sqlalchemy/testing/profiling.py +++ b/lib/sqlalchemy/testing/profiling.py @@ -1,5 +1,5 @@ # testing/profiling.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/requirements.py b/lib/sqlalchemy/testing/requirements.py index 60e966b3b..706d6d060 100644 --- a/lib/sqlalchemy/testing/requirements.py +++ b/lib/sqlalchemy/testing/requirements.py @@ -1,5 +1,5 @@ # testing/requirements.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/runner.py b/lib/sqlalchemy/testing/runner.py index 67e7fddc1..19aba53df 100644 --- a/lib/sqlalchemy/testing/runner.py +++ b/lib/sqlalchemy/testing/runner.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # testing/runner.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/schema.py b/lib/sqlalchemy/testing/schema.py index 93dddc5a7..ec0085219 100644 --- a/lib/sqlalchemy/testing/schema.py +++ b/lib/sqlalchemy/testing/schema.py @@ -1,5 +1,5 @@ # testing/schema.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/util.py b/lib/sqlalchemy/testing/util.py index da6e70eee..bde11a356 100644 --- a/lib/sqlalchemy/testing/util.py +++ b/lib/sqlalchemy/testing/util.py @@ -1,5 +1,5 @@ # testing/util.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php diff --git a/lib/sqlalchemy/testing/warnings.py b/lib/sqlalchemy/testing/warnings.py index abc33f60b..74a8933a6 100644 --- a/lib/sqlalchemy/testing/warnings.py +++ b/lib/sqlalchemy/testing/warnings.py @@ -1,5 +1,5 @@ # testing/warnings.py -# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors +# Copyright (C) 2005-2014 the SQLAlchemy authors and contributors # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php -- cgit v1.2.1 From 1d4f0df35dd7232258670101bca426ec0a5d5c56 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 9 Jan 2014 23:20:00 -0500 Subject: - fix some function mismatch in profiling --- lib/sqlalchemy/testing/profiling.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/profiling.py b/lib/sqlalchemy/testing/profiling.py index 8f5f3f70a..fa2490649 100644 --- a/lib/sqlalchemy/testing/profiling.py +++ b/lib/sqlalchemy/testing/profiling.py @@ -51,12 +51,10 @@ def profiled(target=None, **target_opts): if target is None: target = 'anonymous_target' - filename = "%s.prof" % target - @decorator def decorate(fn, *args, **kw): elapsed, load_stats, result = _profile( - filename, fn, *args, **kw) + fn, *args, **kw) graphic = target_opts.get('graphic', profile_config['graphic']) if graphic: @@ -66,8 +64,8 @@ def profiled(target=None, **target_opts): if report: sort_ = target_opts.get('sort', profile_config['sort']) limit = target_opts.get('limit', profile_config['limit']) - print(("Profile report for target '%s' (%s)" % ( - target, filename) + print(("Profile report for target '%s'" % ( + target, ) )) stats = load_stats() @@ -87,7 +85,6 @@ def profiled(target=None, **target_opts): if print_callees: stats.print_callees() - os.unlink(filename) return result return decorate -- cgit v1.2.1 From bebf30e34d669a5ede54e512e55ee5186fe015f6 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 13 Jan 2014 03:22:11 -0500 Subject: - continue with [ticket:2907] and further clean up how we set up _reset_agent, so that it's local to the various begin_impl(), rollback_impl(), etc. this allows setting/resetting of the flag to be symmetric. - don't set _reset_agent if it's not None, don't unset it if it isn't our own transaction. - make sure we clean it out in close(). - basically, we're dealing here with pools using "threadlocal" that have a counter, other various mismatches that the tests bring up - test for recover() now has to invalidate() the previous connection, because closing it actually rolls it back (e.g. this test was relying on the broken behavior). --- lib/sqlalchemy/testing/engines.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/engines.py b/lib/sqlalchemy/testing/engines.py index d240645a8..a74bffe26 100644 --- a/lib/sqlalchemy/testing/engines.py +++ b/lib/sqlalchemy/testing/engines.py @@ -32,6 +32,9 @@ class ConnectionKiller(object): def checkout(self, dbapi_con, con_record, con_proxy): self.proxy_refs[con_proxy] = True + def invalidate(self, dbapi_con, con_record, exception): + self.conns.discard((dbapi_con, con_record)) + def _safe(self, fn): try: fn() @@ -49,7 +52,7 @@ class ConnectionKiller(object): def close_all(self): for rec in list(self.proxy_refs): - if rec is not None: + if rec is not None and rec.is_valid: self._safe(rec._close) def _after_test_ctx(self): @@ -226,6 +229,7 @@ def testing_engine(url=None, options=None): if use_reaper: event.listen(engine.pool, 'connect', testing_reaper.connect) event.listen(engine.pool, 'checkout', testing_reaper.checkout) + event.listen(engine.pool, 'invalidate', testing_reaper.invalidate) testing_reaper.add_engine(engine) return engine -- cgit v1.2.1 From 52b25c5319b982486348069e2d9edd5259be03d3 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 13 Jan 2014 21:20:54 -0500 Subject: - _cursor_execute() will close the cursor on error; oracle doesn't allow double close - ensure no iterator changed size issues in testing.engines --- lib/sqlalchemy/testing/engines.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/engines.py b/lib/sqlalchemy/testing/engines.py index a74bffe26..d85771f8a 100644 --- a/lib/sqlalchemy/testing/engines.py +++ b/lib/sqlalchemy/testing/engines.py @@ -61,7 +61,7 @@ class ConnectionKiller(object): # is collecting in finalize_fairy, deadlock. # not sure if this should be if pypy/jython only. # note that firebird/fdb definitely needs this though - for conn, rec in self.conns: + for conn, rec in list(self.conns): self._safe(conn.rollback) def _stop_test_ctx(self): @@ -81,7 +81,7 @@ class ConnectionKiller(object): def _stop_test_ctx_aggressive(self): self.close_all() - for conn, rec in self.conns: + for conn, rec in list(self.conns): self._safe(conn.close) rec.connection = None -- cgit v1.2.1 From 44cba66cb2eb4411b43c228c4f1191c764607855 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 20 Jan 2014 16:09:40 -0500 Subject: - repair signature for base get_unique_constraints() method - test_autoincrement_col still needs reflection overall --- lib/sqlalchemy/testing/suite/test_reflection.py | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/suite/test_reflection.py b/lib/sqlalchemy/testing/suite/test_reflection.py index b30f32cff..9f737bc64 100644 --- a/lib/sqlalchemy/testing/suite/test_reflection.py +++ b/lib/sqlalchemy/testing/suite/test_reflection.py @@ -455,6 +455,7 @@ class ComponentReflectionTest(fixtures.TablesTest): def test_get_table_oid_with_schema(self): self._test_get_table_oid('users', schema='test_schema') + @testing.requires.table_reflection @testing.provide_metadata def test_autoincrement_col(self): """test that 'autoincrement' is reflected according to sqla's policy. -- cgit v1.2.1