From 73a4ca028670f284a8f6779dbb7ade35923b0721 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 28 May 2011 20:24:57 -0400 Subject: [PATCH] - move Operators and ColumnOperators into sqlalchemy.sql.operators - since this is strictly a system of routing Python operators into functions. Keep the references available in expression.py for the near future. --- doc/build/core/expression_api.rst | 4 +- lib/sqlalchemy/__init__.py | 2 +- lib/sqlalchemy/orm/interfaces.py | 4 +- lib/sqlalchemy/sql/expression.py | 425 +----------------------------- lib/sqlalchemy/sql/operators.py | 424 +++++++++++++++++++++++++++++ 5 files changed, 430 insertions(+), 429 deletions(-) diff --git a/doc/build/core/expression_api.rst b/doc/build/core/expression_api.rst index b5e47b6ac2..fee9c9501f 100644 --- a/doc/build/core/expression_api.rst +++ b/doc/build/core/expression_api.rst @@ -134,7 +134,7 @@ Classes :members: :show-inheritance: -.. autoclass:: ColumnOperators +.. autoclass:: sqlalchemy.sql.operators.ColumnOperators :members: :undoc-members: :inherited-members: @@ -191,7 +191,7 @@ Classes :members: :show-inheritance: -.. autoclass:: Operators +.. autoclass:: sqlalchemy.sql.expression.Operators :members: :undoc-members: diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py index 6d8a082584..5da63c9af8 100644 --- a/lib/sqlalchemy/__init__.py +++ b/lib/sqlalchemy/__init__.py @@ -117,6 +117,6 @@ from sqlalchemy.engine import create_engine, engine_from_config __all__ = sorted(name for name, obj in locals().items() if not (name.startswith('_') or inspect.ismodule(obj))) -__version__ = '0.7.0' +__version__ = '0.7.1' del inspect, sys diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py index 93200d371c..62d0fb79f7 100644 --- a/lib/sqlalchemy/orm/interfaces.py +++ b/lib/sqlalchemy/orm/interfaces.py @@ -20,7 +20,7 @@ from itertools import chain from sqlalchemy import exc as sa_exc from sqlalchemy import util -from sqlalchemy.sql import expression +from sqlalchemy.sql import operators deque = util.importlater('collections').deque mapperutil = util.importlater('sqlalchemy.orm', 'util') @@ -179,7 +179,7 @@ class MapperProperty(object): return operator(self.comparator, value) -class PropComparator(expression.ColumnOperators): +class PropComparator(operators.ColumnOperators): """Defines comparison operations for MapperProperty objects. User-defined subclasses of :class:`.PropComparator` may be created. The diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index 0d98c89e5a..47f19806a6 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -31,6 +31,7 @@ from operator import attrgetter from sqlalchemy import util, exc from sqlalchemy.sql import operators +from sqlalchemy.sql.operators import Operators, ColumnOperators from sqlalchemy.sql.visitors import Visitable, cloned_traverse import operator @@ -1665,430 +1666,6 @@ class _Immutable(object): def _clone(self): 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): - """Implement the ``&`` operator. - - When used with SQL expressions, results in an - AND operation, equivalent to - :func:`~.expression.and_`, that is:: - - a & b - - is equivalent to:: - - from sqlalchemy import and_ - and_(a, b) - - Care should be taken when using ``&`` regarding - operator precedence; the ``&`` operator has the highest precedence. - The operands should be enclosed in parenthesis if they contain - further sub expressions:: - - (a == 2) & (b == 4) - - """ - return self.operate(operators.and_, other) - - def __or__(self, other): - """Implement the ``|`` operator. - - When used with SQL expressions, results in an - OR operation, equivalent to - :func:`~.expression.or_`, that is:: - - a | b - - is equivalent to:: - - from sqlalchemy import or_ - or_(a, b) - - Care should be taken when using ``|`` regarding - operator precedence; the ``|`` operator has the highest precedence. - The operands should be enclosed in parenthesis if they contain - further sub expressions:: - - (a == 2) | (b == 4) - - """ - return self.operate(operators.or_, other) - - def __invert__(self): - """Implement the ``~`` operator. - - When used with SQL expressions, results in a - NOT operation, equivalent to - :func:`~.expression.not_`, that is:: - - ~a - - is equivalent to:: - - from sqlalchemy import not_ - not_(a) - - """ - return self.operate(operators.inv) - - def op(self, opstring): - """produce a generic operator function. - - e.g.:: - - somecolumn.op("*")(5) - - produces:: - - somecolumn * 5 - - :param operator: a string which will be output as the infix operator - between this :class:`.ClauseElement` and the expression passed to the - generated function. - - This function can also be used to make bitwise operators explicit. For - example:: - - somecolumn.op('&')(0xff) - - is a bitwise AND of the value in somecolumn. - - """ - def op(b): - return self.operate(operators.op, opstring, b) - 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. - - 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. - - The docstrings here will describe column-oriented - behavior of each operator. For ORM-based operators - on related objects and collections, see :class:`.RelationshipProperty.Comparator`. - - """ - - timetuple = None - """Hack, allows datetime objects to be compared on the LHS.""" - - def __lt__(self, other): - """Implement the ``<`` operator. - - In a column context, produces the clause ``a < b``. - - """ - return self.operate(operators.lt, other) - - def __le__(self, other): - """Implement the ``<=`` operator. - - In a column context, produces the clause ``a <= b``. - - """ - return self.operate(operators.le, other) - - __hash__ = Operators.__hash__ - - def __eq__(self, other): - """Implement the ``==`` operator. - - In a column context, produces the clause ``a = b``. - If the target is ``None``, produces ``a IS NULL``. - - """ - return self.operate(operators.eq, other) - - def __ne__(self, other): - """Implement the ``!=`` operator. - - In a column context, produces the clause ``a != b``. - If the target is ``None``, produces ``a IS NOT NULL``. - - """ - return self.operate(operators.ne, other) - - def __gt__(self, other): - """Implement the ``>`` operator. - - In a column context, produces the clause ``a > b``. - - """ - return self.operate(operators.gt, other) - - def __ge__(self, other): - """Implement the ``>=`` operator. - - In a column context, produces the clause ``a >= b``. - - """ - return self.operate(operators.ge, other) - - def __neg__(self): - """Implement the ``-`` operator. - - In a column context, produces the clause ``-a``. - - """ - return self.operate(operators.neg) - - def concat(self, other): - """Implement the 'concat' operator. - - In a column context, produces the clause ``a || b``, - or uses the ``concat()`` operator on MySQL. - - """ - return self.operate(operators.concat_op, other) - - def like(self, other, escape=None): - """Implement the ``like`` operator. - - In a column context, produces the clause ``a LIKE other``. - - """ - return self.operate(operators.like_op, other, escape=escape) - - def ilike(self, other, escape=None): - """Implement the ``ilike`` operator. - - In a column context, produces the clause ``a ILIKE other``. - - """ - return self.operate(operators.ilike_op, other, escape=escape) - - def in_(self, other): - """Implement the ``in`` operator. - - In a column context, produces the clause ``a IN other``. - "other" may be a tuple/list of column expressions, - or a :func:`~.expression.select` construct. - - """ - return self.operate(operators.in_op, other) - - def startswith(self, other, **kwargs): - """Implement the ``startwith`` operator. - - In a column context, produces the clause ``LIKE '%'`` - - """ - return self.operate(operators.startswith_op, other, **kwargs) - - def endswith(self, other, **kwargs): - """Implement the 'endswith' operator. - - In a column context, produces the clause ``LIKE '%'`` - - """ - return self.operate(operators.endswith_op, other, **kwargs) - - def contains(self, other, **kwargs): - """Implement the 'contains' operator. - - In a column context, produces the clause ``LIKE '%%'`` - - """ - return self.operate(operators.contains_op, other, **kwargs) - - def match(self, other, **kwargs): - """Implements the 'match' operator. - - In a column context, this produces a MATCH clause, i.e. - ``MATCH ''``. The allowed contents of ``other`` - are database backend specific. - - """ - return self.operate(operators.match_op, other, **kwargs) - - def desc(self): - """Produce a :func:`~.expression.desc` clause against the - parent object.""" - return self.operate(operators.desc_op) - - def asc(self): - """Produce a :func:`~.expression.asc` clause against the - parent object.""" - return self.operate(operators.asc_op) - - def nullsfirst(self): - """Produce a :func:`~.expression.nullsfirst` clause against the - parent object.""" - return self.operate(operators.nullsfirst_op) - - def nullslast(self): - """Produce a :func:`~.expression.nullslast` clause against the - parent object.""" - return self.operate(operators.nullslast_op) - - def collate(self, collation): - """Produce a :func:`~.expression.collate` clause against - the parent object, given the collation string.""" - return self.operate(operators.collate, collation) - - def __radd__(self, other): - """Implement the ``+`` operator in reverse. - - See :meth:`__add__`. - - """ - return self.reverse_operate(operators.add, other) - - def __rsub__(self, other): - """Implement the ``-`` operator in reverse. - - See :meth:`__sub__`. - - """ - return self.reverse_operate(operators.sub, other) - - def __rmul__(self, other): - """Implement the ``*`` operator in reverse. - - See :meth:`__mul__`. - - """ - return self.reverse_operate(operators.mul, other) - - def __rdiv__(self, other): - """Implement the ``/`` operator in reverse. - - See :meth:`__div__`. - - """ - return self.reverse_operate(operators.div, other) - - def between(self, cleft, cright): - """Produce a :func:`~.expression.between` clause against - the parent object, given the lower and upper range.""" - return self.operate(operators.between_op, cleft, cright) - - def distinct(self): - """Produce a :func:`~.expression.distinct` clause against the parent object.""" - return self.operate(operators.distinct_op) - - def __add__(self, other): - """Implement the ``+`` operator. - - In a column context, produces the clause ``a + b`` - if the parent object has non-string affinity. - If the parent object has a string affinity, - produces the concatenation operator, ``a || b`` - - see :meth:`concat`. - - """ - return self.operate(operators.add, other) - - def __sub__(self, other): - """Implement the ``-`` operator. - - In a column context, produces the clause ``a - b``. - - """ - return self.operate(operators.sub, other) - - def __mul__(self, other): - """Implement the ``*`` operator. - - In a column context, produces the clause ``a * b``. - - """ - return self.operate(operators.mul, other) - - def __div__(self, other): - """Implement the ``/`` operator. - - In a column context, produces the clause ``a / b``. - - """ - return self.operate(operators.div, other) - - def __mod__(self, other): - """Implement the ``%`` operator. - - In a column context, produces the clause ``a % b``. - - """ - return self.operate(operators.mod, other) - - def __truediv__(self, other): - """Implement the ``//`` operator. - - In a column context, produces the clause ``a / b``. - - """ - return self.operate(operators.truediv, other) - - def __rtruediv__(self, other): - """Implement the ``//`` operator in reverse. - - See :meth:`__truediv__`. - - """ - return self.reverse_operate(operators.truediv, other) class _CompareMixin(ColumnOperators): """Defines comparison and math operations for :class:`.ClauseElement` diff --git a/lib/sqlalchemy/sql/operators.py b/lib/sqlalchemy/sql/operators.py index 494f76f140..dcea5a0f6d 100644 --- a/lib/sqlalchemy/sql/operators.py +++ b/lib/sqlalchemy/sql/operators.py @@ -19,6 +19,430 @@ from operator import (div,) from sqlalchemy.util import symbol +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): + """Implement the ``&`` operator. + + When used with SQL expressions, results in an + AND operation, equivalent to + :func:`~.expression.and_`, that is:: + + a & b + + is equivalent to:: + + from sqlalchemy import and_ + and_(a, b) + + Care should be taken when using ``&`` regarding + operator precedence; the ``&`` operator has the highest precedence. + The operands should be enclosed in parenthesis if they contain + further sub expressions:: + + (a == 2) & (b == 4) + + """ + return self.operate(and_, other) + + def __or__(self, other): + """Implement the ``|`` operator. + + When used with SQL expressions, results in an + OR operation, equivalent to + :func:`~.expression.or_`, that is:: + + a | b + + is equivalent to:: + + from sqlalchemy import or_ + or_(a, b) + + Care should be taken when using ``|`` regarding + operator precedence; the ``|`` operator has the highest precedence. + The operands should be enclosed in parenthesis if they contain + further sub expressions:: + + (a == 2) | (b == 4) + + """ + return self.operate(or_, other) + + def __invert__(self): + """Implement the ``~`` operator. + + When used with SQL expressions, results in a + NOT operation, equivalent to + :func:`~.expression.not_`, that is:: + + ~a + + is equivalent to:: + + from sqlalchemy import not_ + not_(a) + + """ + return self.operate(inv) + + def op(self, opstring): + """produce a generic operator function. + + e.g.:: + + somecolumn.op("*")(5) + + produces:: + + somecolumn * 5 + + :param operator: a string which will be output as the infix operator + between this :class:`.ClauseElement` and the expression passed to the + generated function. + + This function can also be used to make bitwise operators explicit. For + example:: + + somecolumn.op('&')(0xff) + + is a bitwise AND of the value in somecolumn. + + """ + def _op(b): + return self.operate(op, opstring, b) + 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. + + 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. + + The docstrings here will describe column-oriented + behavior of each operator. For ORM-based operators + on related objects and collections, see :class:`.RelationshipProperty.Comparator`. + + """ + + timetuple = None + """Hack, allows datetime objects to be compared on the LHS.""" + + def __lt__(self, other): + """Implement the ``<`` operator. + + In a column context, produces the clause ``a < b``. + + """ + return self.operate(lt, other) + + def __le__(self, other): + """Implement the ``<=`` operator. + + In a column context, produces the clause ``a <= b``. + + """ + return self.operate(le, other) + + __hash__ = Operators.__hash__ + + def __eq__(self, other): + """Implement the ``==`` operator. + + In a column context, produces the clause ``a = b``. + If the target is ``None``, produces ``a IS NULL``. + + """ + return self.operate(eq, other) + + def __ne__(self, other): + """Implement the ``!=`` operator. + + In a column context, produces the clause ``a != b``. + If the target is ``None``, produces ``a IS NOT NULL``. + + """ + return self.operate(ne, other) + + def __gt__(self, other): + """Implement the ``>`` operator. + + In a column context, produces the clause ``a > b``. + + """ + return self.operate(gt, other) + + def __ge__(self, other): + """Implement the ``>=`` operator. + + In a column context, produces the clause ``a >= b``. + + """ + return self.operate(ge, other) + + def __neg__(self): + """Implement the ``-`` operator. + + In a column context, produces the clause ``-a``. + + """ + return self.operate(neg) + + def concat(self, other): + """Implement the 'concat' operator. + + In a column context, produces the clause ``a || b``, + or uses the ``concat()`` operator on MySQL. + + """ + return self.operate(concat_op, other) + + def like(self, other, escape=None): + """Implement the ``like`` operator. + + In a column context, produces the clause ``a LIKE other``. + + """ + return self.operate(like_op, other, escape=escape) + + def ilike(self, other, escape=None): + """Implement the ``ilike`` operator. + + In a column context, produces the clause ``a ILIKE other``. + + """ + return self.operate(ilike_op, other, escape=escape) + + def in_(self, other): + """Implement the ``in`` operator. + + In a column context, produces the clause ``a IN other``. + "other" may be a tuple/list of column expressions, + or a :func:`~.expression.select` construct. + + """ + return self.operate(in_op, other) + + def startswith(self, other, **kwargs): + """Implement the ``startwith`` operator. + + In a column context, produces the clause ``LIKE '%'`` + + """ + return self.operate(startswith_op, other, **kwargs) + + def endswith(self, other, **kwargs): + """Implement the 'endswith' operator. + + In a column context, produces the clause ``LIKE '%'`` + + """ + return self.operate(endswith_op, other, **kwargs) + + def contains(self, other, **kwargs): + """Implement the 'contains' operator. + + In a column context, produces the clause ``LIKE '%%'`` + + """ + return self.operate(contains_op, other, **kwargs) + + def match(self, other, **kwargs): + """Implements the 'match' operator. + + In a column context, this produces a MATCH clause, i.e. + ``MATCH ''``. The allowed contents of ``other`` + are database backend specific. + + """ + return self.operate(match_op, other, **kwargs) + + def desc(self): + """Produce a :func:`~.expression.desc` clause against the + parent object.""" + return self.operate(desc_op) + + def asc(self): + """Produce a :func:`~.expression.asc` clause against the + parent object.""" + return self.operate(asc_op) + + def nullsfirst(self): + """Produce a :func:`~.expression.nullsfirst` clause against the + parent object.""" + return self.operate(nullsfirst_op) + + def nullslast(self): + """Produce a :func:`~.expression.nullslast` clause against the + parent object.""" + return self.operate(nullslast_op) + + def collate(self, collation): + """Produce a :func:`~.expression.collate` clause against + the parent object, given the collation string.""" + return self.operate(collate, collation) + + def __radd__(self, other): + """Implement the ``+`` operator in reverse. + + See :meth:`__add__`. + + """ + return self.reverse_operate(add, other) + + def __rsub__(self, other): + """Implement the ``-`` operator in reverse. + + See :meth:`__sub__`. + + """ + return self.reverse_operate(sub, other) + + def __rmul__(self, other): + """Implement the ``*`` operator in reverse. + + See :meth:`__mul__`. + + """ + return self.reverse_operate(mul, other) + + def __rdiv__(self, other): + """Implement the ``/`` operator in reverse. + + See :meth:`__div__`. + + """ + return self.reverse_operate(div, other) + + def between(self, cleft, cright): + """Produce a :func:`~.expression.between` clause against + the parent object, given the lower and upper range.""" + return self.operate(between_op, cleft, cright) + + def distinct(self): + """Produce a :func:`~.expression.distinct` clause against the parent object.""" + return self.operate(distinct_op) + + def __add__(self, other): + """Implement the ``+`` operator. + + In a column context, produces the clause ``a + b`` + if the parent object has non-string affinity. + If the parent object has a string affinity, + produces the concatenation operator, ``a || b`` - + see :meth:`concat`. + + """ + return self.operate(add, other) + + def __sub__(self, other): + """Implement the ``-`` operator. + + In a column context, produces the clause ``a - b``. + + """ + return self.operate(sub, other) + + def __mul__(self, other): + """Implement the ``*`` operator. + + In a column context, produces the clause ``a * b``. + + """ + return self.operate(mul, other) + + def __div__(self, other): + """Implement the ``/`` operator. + + In a column context, produces the clause ``a / b``. + + """ + return self.operate(div, other) + + def __mod__(self, other): + """Implement the ``%`` operator. + + In a column context, produces the clause ``a % b``. + + """ + return self.operate(mod, other) + + def __truediv__(self, other): + """Implement the ``//`` operator. + + In a column context, produces the clause ``a / b``. + + """ + return self.operate(truediv, other) + + def __rtruediv__(self, other): + """Implement the ``//`` operator in reverse. + + See :meth:`__truediv__`. + + """ + return self.reverse_operate(truediv, other) def from_(): raise NotImplementedError() -- 2.39.5