diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-09-01 10:35:30 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-09-01 12:34:41 -0400 |
commit | 919b8bc4acf8de4720e8fff5077557f366fb3fb0 (patch) | |
tree | fd515dc511a722b8a464c2c851cb59ddb4bda907 /lib/sqlalchemy/sql/operators.py | |
parent | 65680b2343ef421a62582e23e2b35293732933ad (diff) | |
download | sqlalchemy-919b8bc4acf8de4720e8fff5077557f366fb3fb0.tar.gz |
Ensure custom ops have consistent typing behavior, boolean support
Refined the behavior of :meth:`.Operators.op` such that in all cases,
if the :paramref:`.Operators.op.is_comparison` flag is set to True,
the return type of the resulting expression will be
:class:`.Boolean`, and if the flag is False, the return type of the
resulting expression will be the same type as that of the left-hand
expression, which is the typical default behavior of other operators.
Also added a new parameter :paramref:`.Operators.op.return_type` as well
as a helper method :meth:`.Operators.bool_op`.
Change-Id: Ifc8553cd4037d741b84b70a9702cbd530f1a9de0
Fixes: #4063
Diffstat (limited to 'lib/sqlalchemy/sql/operators.py')
-rw-r--r-- | lib/sqlalchemy/sql/operators.py | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/lib/sqlalchemy/sql/operators.py b/lib/sqlalchemy/sql/operators.py index f8731385b..a14afcb70 100644 --- a/lib/sqlalchemy/sql/operators.py +++ b/lib/sqlalchemy/sql/operators.py @@ -104,7 +104,9 @@ class Operators(object): """ return self.operate(inv) - def op(self, opstring, precedence=0, is_comparison=False): + def op( + self, opstring, precedence=0, is_comparison=False, + return_type=None): """produce a generic operator function. e.g.:: @@ -145,6 +147,16 @@ class Operators(object): .. versionadded:: 0.9.2 - added the :paramref:`.Operators.op.is_comparison` flag. + :param return_type: a :class:`.TypeEngine` class or object that will + force the return type of an expression produced by this operator + to be of that type. By default, operators that specify + :paramref:`.Operators.op.is_comparison` will resolve to + :class:`.Boolean`, and those that do not will be of the same + type as the left-hand operand. + + .. versionadded:: 1.2.0b3 - added the + :paramref:`.Operators.op.return_type` argument. + .. seealso:: :ref:`types_operators` @@ -152,12 +164,29 @@ class Operators(object): :ref:`relationship_custom_operator` """ - operator = custom_op(opstring, precedence, is_comparison) + operator = custom_op(opstring, precedence, is_comparison, return_type) def against(other): return operator(self, other) return against + def bool_op(self, opstring, precedence=0): + """Return a custom boolean operator. + + This method is shorthand for calling + :meth:`.Operators.op` and passing the + :paramref:`.Operators.op.is_comparison` + flag with True. + + .. versionadded:: 1.2.0b3 + + .. seealso:: + + :meth:`.Operators.op` + + """ + return self.op(opstring, precedence=precedence, is_comparison=True) + def operate(self, op, *other, **kwargs): r"""Operate on an argument. @@ -197,9 +226,9 @@ class custom_op(object): """Represent a 'custom' operator. :class:`.custom_op` is normally instantiated when the - :meth:`.ColumnOperators.op` method is used to create a - custom operator callable. The class can also be used directly - when programmatically constructing expressions. E.g. + :meth:`.Operators.op` or :meth:`.Operators.bool_op` methods + are used to create a custom operator callable. The class can also be + used directly when programmatically constructing expressions. E.g. to represent the "factorial" operation:: from sqlalchemy.sql import UnaryExpression @@ -210,17 +239,28 @@ class custom_op(object): modifier=operators.custom_op("!"), type_=Numeric) + + .. seealso:: + + :meth:`.Operators.op` + + :meth:`.Operators.bool_op` + """ __name__ = 'custom_op' def __init__( self, opstring, precedence=0, is_comparison=False, - natural_self_precedent=False, eager_grouping=False): + return_type=None, natural_self_precedent=False, + eager_grouping=False): self.opstring = opstring self.precedence = precedence self.is_comparison = is_comparison self.natural_self_precedent = natural_self_precedent self.eager_grouping = eager_grouping + self.return_type = ( + return_type._to_instance(return_type) if return_type else None + ) def __eq__(self, other): return isinstance(other, custom_op) and \ |