diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-08-13 16:53:38 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-08-13 16:53:38 -0400 |
commit | 2937f94e4a05be5b8db268b47745157a143ca30e (patch) | |
tree | cbc5b1eb4dfdc1a1bef9a0eb592ea716f45bec1f | |
parent | 37fad88b84db61fba0a09a1c76bcf95d055aa6e2 (diff) | |
download | sqlalchemy-2937f94e4a05be5b8db268b47745157a143ca30e.tar.gz |
- all tests pass
-rw-r--r-- | lib/sqlalchemy/orm/interfaces.py | 3 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/properties.py | 11 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/expression.py | 58 | ||||
-rw-r--r-- | test/lib/profiles.txt | 19 | ||||
-rw-r--r-- | test/orm/test_mapper.py | 6 | ||||
-rw-r--r-- | test/sql/test_compiler.py | 2 | ||||
-rw-r--r-- | test/sql/test_query.py | 8 |
7 files changed, 53 insertions, 54 deletions
diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py index f2014e964..d0732b913 100644 --- a/lib/sqlalchemy/orm/interfaces.py +++ b/lib/sqlalchemy/orm/interfaces.py @@ -237,9 +237,6 @@ class PropComparator(operators.ColumnOperators): return self.__class__(self.prop, self.mapper, adapter) - def __getattr__(self, key): - return getattr(self.__clause_element__(), key) - @staticmethod def any_op(a, b, **kwargs): return a.any(b, **kwargs) diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 53ee1b5fd..62e4672d3 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -168,7 +168,14 @@ class ColumnProperty(StrategizedProperty): else: return self.prop.columns[0]._annotate({ "parententity": self.mapper, - "parentmapper":self.mapper}) + "parentmapper": self.mapper}) + + def __getattr__(self, key): + """proxy attribute access down to the mapped column. + + this allows user-defined comparison methods to be accessed. + """ + return getattr(self.__clause_element__(), key) def operate(self, op, *other, **kwargs): return op(self.__clause_element__(), *other, **kwargs) @@ -254,7 +261,7 @@ class RelationshipProperty(StrategizedProperty): if strategy_class: self.strategy_class = strategy_class - elif self.lazy== 'dynamic': + elif self.lazy == 'dynamic': from sqlalchemy.orm import dynamic self.strategy_class = dynamic.DynaLoader else: diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index b92ec4529..6021b40b1 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -1988,55 +1988,58 @@ class _DefaultColumnComparator(ColumnOperators): return self.__compare(expr, op, ClauseList(*args).self_group(against=op), negate=negate_op) - def _neg_impl(self): + def _neg_impl(self, expr, op, **kw): """See :meth:`.ColumnOperators.__neg__`.""" - return UnaryExpression(self.expr, operator=operators.neg) + return UnaryExpression(expr, operator=operators.neg) - def _startswith_impl(self, other, escape=None): + def _startswith_impl(self, expr, op, other, escape=None): """See :meth:`.ColumnOperators.startswith`.""" # use __radd__ to force string concat behavior return self.__compare( + expr, operators.like_op, literal_column("'%'", type_=sqltypes.String).__radd__( - self._check_literal(operators.like_op, other) + self._check_literal(expr, operators.like_op, other) ), escape=escape) - def _endswith_impl(self, other, escape=None): + def _endswith_impl(self, expr, op, other, escape=None): """See :meth:`.ColumnOperators.endswith`.""" return self.__compare( + expr, operators.like_op, literal_column("'%'", type_=sqltypes.String) + - self._check_literal(operators.like_op, other), + self._check_literal(expr, operators.like_op, other), escape=escape) - def _contains_impl(self, other, escape=None): + def _contains_impl(self, expr, op, other, escape=None): """See :meth:`.ColumnOperators.contains`.""" return self.__compare( + expr, operators.like_op, literal_column("'%'", type_=sqltypes.String) + - self._check_literal(operators.like_op, other) + + self._check_literal(expr, operators.like_op, other) + literal_column("'%'", type_=sqltypes.String), escape=escape) - def _match_impl(self, other): + def _match_impl(self, expr, op, other): """See :meth:`.ColumnOperators.match`.""" - return self.__compare(operators.match_op, - self._check_literal(operators.match_op, + return self.__compare(expr, operators.match_op, + self._check_literal(expr, operators.match_op, other)) - def _distinct_impl(self): + def _distinct_impl(self, expr, op): """See :meth:`.ColumnOperators.distinct`.""" - return UnaryExpression(self, operator=operators.distinct_op, - type_=self.type) + return UnaryExpression(expr, operator=operators.distinct_op, + type_=expr.type) - def _between_impl(self, cleft, cright): + def _between_impl(self, expr, op, cleft, cright, **kw): """See :meth:`.ColumnOperators.between`.""" return BinaryExpression( - self, + expr, ClauseList( - self._check_literal(operators.and_, cleft), - self._check_literal(operators.and_, cright), + self._check_literal(expr, operators.and_, cleft), + self._check_literal(expr, operators.and_, cright), operator=operators.and_, group=False), operators.between_op) @@ -2068,6 +2071,13 @@ class _DefaultColumnComparator(ColumnOperators): "nullslast_op": (__scalar, nullslast), "in_op": (_in_impl, operators.notin_op), "collate": (_collate_impl,), + "match_op": (_match_impl,), + "distinct_op": (_distinct_impl,), + "between_op": (_between_impl, ), + "contains_op": (_contains_impl, ), + "startswith_op": (_startswith_impl,), + "endswith_op": (_endswith_impl,), + "neg": (_neg_impl,), } def operate(self, expr, op, *other, **kwargs): @@ -2194,7 +2204,7 @@ class ColumnElement(ClauseElement, ColumnOperators): if self.comparator: return op(other, self.comparator, **kwargs) else: - return _DEFAULT_COMPARATOR.reverse_operate(self, op, *other, **kwargs) + return _DEFAULT_COMPARATOR.reverse_operate(self, op, other, **kwargs) def _bind_param(self, operator, obj): return BindParameter(None, obj, @@ -3130,13 +3140,6 @@ class ClauseList(ClauseElement): _literal_as_text(clause) for clause in clauses if clause is not None] - @util.memoized_property - def type(self): - if self.clauses: - return self.clauses[0].type - else: - return sqltypes.NULLTYPE - def __iter__(self): return iter(self.clauses) @@ -4288,8 +4291,7 @@ class ColumnClause(Immutable, ColumnElement): _as_truncated(name if name else self.name), selectable=selectable, type_=self.type, - is_literal=is_literal, - comparator_factory=self.comparator_factory + is_literal=is_literal ) c.proxies = [self] if selectable._is_clone_of is not None: diff --git a/test/lib/profiles.txt b/test/lib/profiles.txt index db427d701..5572a8ebc 100644 --- a/test/lib/profiles.txt +++ b/test/lib/profiles.txt @@ -1,4 +1,4 @@ -# /Users/classic/dev/sqlalchemy/./test/lib/profiles.txt +# /Users/classic/dev/sqla_comparators/./test/lib/profiles.txt # This file is written out on a per-environment basis. # For each test in aaa_profiling, the corresponding function and # environment is located within this file. If it doesn't exist, @@ -195,16 +195,13 @@ test.aaa_profiling.test_resultset.ExecutionTest.test_minimal_engine_execute 3.2_ # TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.5_sqlite_pysqlite_nocextensions 9 -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.6_sqlite_pysqlite_nocextensions 9 -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_cextensions 9 -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_nocextensions 9 -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_cextensions 9 -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_nocextensions 9 -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_cextensions 9 -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_nocextensions 9 -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.2_postgresql_psycopg2_nocextensions 10 -test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 3.2_sqlite_pysqlite_nocextensions 10 +test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.6_sqlite_pysqlite_nocextensions 12 +test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_cextensions 12 +test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_mysql_mysqldb_nocextensions 12 +test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_cextensions 12 +test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_postgresql_psycopg2_nocextensions 12 +test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_cextensions 12 +test.aaa_profiling.test_resultset.ResultSetTest.test_contains_doesnt_compile 2.7_sqlite_pysqlite_nocextensions 12 # TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_string diff --git a/test/orm/test_mapper.py b/test/orm/test_mapper.py index 9e6e7fbbf..a87c064cf 100644 --- a/test/orm/test_mapper.py +++ b/test/orm/test_mapper.py @@ -1269,7 +1269,8 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): def __getitem__(self, key): return 'value' - class UCComparator(sa.orm.PropComparator): + from sqlalchemy.orm.properties import ColumnProperty + class UCComparator(ColumnProperty.Comparator): __hash__ = None def method1(self): @@ -1314,7 +1315,8 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): assert_raises_message( AttributeError, - "Neither 'extendedproperty' object nor 'UCComparator' object has an attribute 'nonexistent'", + "Neither 'extendedproperty' object nor 'UCComparator' " + "object has an attribute 'nonexistent'", getattr, User.uc_name, 'nonexistent') # test compile diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py index aee170d15..64d50a1d5 100644 --- a/test/sql/test_compiler.py +++ b/test/sql/test_compiler.py @@ -940,6 +940,8 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL): table1.c.myid.like('hoho') eq_(str(clause), str(util.pickle.loads(util.pickle.dumps(clause)))) + clause = tuple_(1, 2, 3) + eq_(str(clause), str(util.pickle.loads(util.pickle.dumps(clause)))) def test_like(self): for expr, check, dialect in [ diff --git a/test/sql/test_query.py b/test/sql/test_query.py index 2541d0711..1ae15707a 100644 --- a/test/sql/test_query.py +++ b/test/sql/test_query.py @@ -1012,14 +1012,6 @@ class QueryTest(fixtures.TestBase): r = testing.db.execute('select user_name from query_users').first() eq_(len(r), 1) - @testing.uses_deprecated(r'.*which subclass Executable') - def test_cant_execute_join(self): - try: - users.join(addresses).execute() - except exc.StatementError, e: - assert str(e).startswith('Not an executable clause ') - - def test_column_order_with_simple_query(self): # should return values in column definition order |