[Sqlalchemy-commits] sqlalchemy: - add some docs to hybrid comparators, operators/com...
Brought to you by:
zzzeek
From: <co...@sq...> - 2011-05-22 19:54:30
|
details: http://hg.sqlalchemy.org/sqlalchemy/sqlalchemy/rev/bd2ec52e6c30 changeset: 7626:bd2ec52e6c30 user: zzzeek date: Sun May 22 15:54:17 2011 -0400 description: - add some docs to hybrid comparators, operators/comparator logic at the base diffstat: doc/build/core/expression_api.rst | 28 +++++++++++++++++ lib/sqlalchemy/ext/hybrid.py | 16 +++++++++- lib/sqlalchemy/sql/expression.py | 63 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 2 deletions(-) diffs (164 lines): diff -r bc992d31dc10 -r bd2ec52e6c30 doc/build/core/expression_api.rst --- a/doc/build/core/expression_api.rst Fri May 20 18:09:29 2011 -0400 +++ b/doc/build/core/expression_api.rst Sun May 22 15:54:17 2011 -0400 @@ -135,6 +135,26 @@ :members: :undoc-members: :inherited-members: + :show-inheritance: + + .. automethod:: __eq__ + .. automethod:: __ne__ + .. automethod:: __gt__ + .. automethod:: __ge__ + .. automethod:: __lt__ + .. automethod:: __le__ + .. automethod:: __neg__ + .. automethod:: __add__ + .. automethod:: __mul__ + .. automethod:: __div__ + .. automethod:: __truediv__ + .. automethod:: __sub__ + .. automethod:: __radd__ + .. automethod:: __rsub__ + .. automethod:: __rtruediv__ + .. automethod:: __rdiv__ + .. automethod:: __rmul__ + .. automethod:: __mod__ .. autoclass:: CompoundSelect :members: @@ -168,6 +188,14 @@ :members: :show-inheritance: +.. autoclass:: Operators + :members: + :undoc-members: + + .. automethod:: __and__ + .. automethod:: __or__ + .. automethod:: __invert__ + .. autoclass:: Select :members: :show-inheritance: diff -r bc992d31dc10 -r bd2ec52e6c30 lib/sqlalchemy/ext/hybrid.py --- a/lib/sqlalchemy/ext/hybrid.py Fri May 20 18:09:29 2011 -0400 +++ b/lib/sqlalchemy/ext/hybrid.py Sun May 22 15:54:17 2011 -0400 @@ -259,7 +259,12 @@ The example class below allows case-insensitive comparisons on the attribute named ``word_insensitive``:: - from sqlalchemy.ext.hybrid import Comparator + from sqlalchemy.ext.hybrid import Comparator, hybrid_property + from sqlalchemy import func, Column, Integer, String + from sqlalchemy.orm import Session + from sqlalchemy.ext.declarative import declarative_base + + Base = declarative_base() class CaseInsensitiveComparator(Comparator): def __eq__(self, other): @@ -286,6 +291,15 @@ FROM searchword WHERE lower(searchword.word) = lower(:lower_1) +The ``CaseInsensitiveComparator`` above implements part of the :class:`.ColumnOperators` +interface. A "coercion" operation like lowercasing can be applied to all comparison operations +(i.e. ``eq``, ``lt``, ``gt``, etc.) using :meth:`.Operators.operate`:: + + class CaseInsensitiveComparator(Comparator): + def operate(self, op, other): + return op(func.lower(self.__clause_element__()), func.lower(other)) + + """ from sqlalchemy import util from sqlalchemy.orm import attributes, interfaces diff -r bc992d31dc10 -r bd2ec52e6c30 lib/sqlalchemy/sql/expression.py --- a/lib/sqlalchemy/sql/expression.py Fri May 20 18:09:29 2011 -0400 +++ b/lib/sqlalchemy/sql/expression.py Sun May 22 15:54:17 2011 -0400 @@ -1631,6 +1631,15 @@ return self class Operators(object): + """Base of comparison and logical operators. + + Implements base methods :meth:`operate` and :meth:`reverse_operate`, + as well as :meth:`__and__`, :meth:`__or__`, :meth:`__invert__`. + + Usually is used via its most common subclass + :class:`.ColumnOperators`. + + """ def __and__(self, other): return self.operate(operators.and_, other) @@ -1646,13 +1655,65 @@ return op def operate(self, op, *other, **kwargs): + """Operate on an argument. + + This is the lowest level of operation, raises + :class:`NotImplementedError` by default. + + Overriding this on a subclass can allow common + behavior to be applied to all operations. + For example, overriding :class:`.ColumnOperators` + to apply ``func.lower()`` to the left and right + side:: + + class MyComparator(ColumnOperators): + def operate(self, op, other): + return op(func.lower(self), func.lower(other)) + + :param op: Operator callable. + :param \*other: the 'other' side of the operation. Will + be a single scalar for most operations. + :param \**kwargs: modifiers. These may be passed by special + operators such as :meth:`ColumnOperators.contains`. + + + """ raise NotImplementedError(str(op)) def reverse_operate(self, op, other, **kwargs): + """Reverse operate on an argument. + + Usage is the same as :meth:`operate`. + + """ raise NotImplementedError(str(op)) class ColumnOperators(Operators): - """Defines comparison and math operations.""" + """Defines comparison and math operations. + + By default all methods call down to + :meth:`Operators.operate` or :meth:`Operators.reverse_operate` + passing in the appropriate operator function from the + Python builtin ``operator`` module or + a SQLAlchemy-specific operator function from + :mod:`sqlalchemy.expression.operators`. For example + the ``__eq__`` function:: + + def __eq__(self, other): + return self.operate(operators.eq, other) + + Where ``operators.eq`` is essentially:: + + def eq(a, b): + return a == b + + A SQLAlchemy construct like :class:`.ColumnElement` ultimately + overrides :meth:`.Operators.operate` and others + to return further :class:`.ClauseElement` constructs, + so that the ``==`` operation above is replaced by a clause + construct. + + """ timetuple = None """Hack, allows datetime objects to be compared on the LHS.""" |