diff options
Diffstat (limited to 'lib/sqlalchemy/sql/default_comparator.py')
-rw-r--r-- | lib/sqlalchemy/sql/default_comparator.py | 234 |
1 files changed, 135 insertions, 99 deletions
diff --git a/lib/sqlalchemy/sql/default_comparator.py b/lib/sqlalchemy/sql/default_comparator.py index 8149f9731..fa0052198 100644 --- a/lib/sqlalchemy/sql/default_comparator.py +++ b/lib/sqlalchemy/sql/default_comparator.py @@ -11,19 +11,43 @@ from .. import exc, util from . import type_api from . import operators -from .elements import BindParameter, True_, False_, BinaryExpression, \ - Null, _const_expr, _clause_element_as_expr, \ - ClauseList, ColumnElement, TextClause, UnaryExpression, \ - collate, _is_literal, _literal_as_text, ClauseElement, and_, or_, \ - Slice, Visitable, _literal_as_binds, CollectionAggregate, \ - Tuple +from .elements import ( + BindParameter, + True_, + False_, + BinaryExpression, + Null, + _const_expr, + _clause_element_as_expr, + ClauseList, + ColumnElement, + TextClause, + UnaryExpression, + collate, + _is_literal, + _literal_as_text, + ClauseElement, + and_, + or_, + Slice, + Visitable, + _literal_as_binds, + CollectionAggregate, + Tuple, +) from .selectable import SelectBase, Alias, Selectable, ScalarSelect -def _boolean_compare(expr, op, obj, negate=None, reverse=False, - _python_is_types=(util.NoneType, bool), - result_type = None, - **kwargs): +def _boolean_compare( + expr, + op, + obj, + negate=None, + reverse=False, + _python_is_types=(util.NoneType, bool), + result_type=None, + **kwargs +): if result_type is None: result_type = type_api.BOOLEANTYPE @@ -33,57 +57,64 @@ def _boolean_compare(expr, op, obj, negate=None, reverse=False, # allow x ==/!= True/False to be treated as a literal. # this comes out to "== / != true/false" or "1/0" if those # constants aren't supported and works on all platforms - if op in (operators.eq, operators.ne) and \ - isinstance(obj, (bool, True_, False_)): - return BinaryExpression(expr, - _literal_as_text(obj), - op, - type_=result_type, - negate=negate, modifiers=kwargs) + if op in (operators.eq, operators.ne) and isinstance( + obj, (bool, True_, False_) + ): + return BinaryExpression( + expr, + _literal_as_text(obj), + op, + type_=result_type, + negate=negate, + modifiers=kwargs, + ) elif op in (operators.is_distinct_from, operators.isnot_distinct_from): - return BinaryExpression(expr, - _literal_as_text(obj), - op, - type_=result_type, - negate=negate, modifiers=kwargs) + return BinaryExpression( + expr, + _literal_as_text(obj), + op, + type_=result_type, + negate=negate, + modifiers=kwargs, + ) else: # all other None/True/False uses IS, IS NOT if op in (operators.eq, operators.is_): - return BinaryExpression(expr, _const_expr(obj), - operators.is_, - negate=operators.isnot, - type_=result_type - ) + return BinaryExpression( + expr, + _const_expr(obj), + operators.is_, + negate=operators.isnot, + type_=result_type, + ) elif op in (operators.ne, operators.isnot): - return BinaryExpression(expr, _const_expr(obj), - operators.isnot, - negate=operators.is_, - type_=result_type - ) + return BinaryExpression( + expr, + _const_expr(obj), + operators.isnot, + negate=operators.is_, + type_=result_type, + ) else: raise exc.ArgumentError( "Only '=', '!=', 'is_()', 'isnot()', " "'is_distinct_from()', 'isnot_distinct_from()' " - "operators can be used with None/True/False") + "operators can be used with None/True/False" + ) else: obj = _check_literal(expr, op, obj) if reverse: - return BinaryExpression(obj, - expr, - op, - type_=result_type, - negate=negate, modifiers=kwargs) + return BinaryExpression( + obj, expr, op, type_=result_type, negate=negate, modifiers=kwargs + ) else: - return BinaryExpression(expr, - obj, - op, - type_=result_type, - negate=negate, modifiers=kwargs) + return BinaryExpression( + expr, obj, op, type_=result_type, negate=negate, modifiers=kwargs + ) -def _custom_op_operate(expr, op, obj, reverse=False, result_type=None, - **kw): +def _custom_op_operate(expr, op, obj, reverse=False, result_type=None, **kw): if result_type is None: if op.return_type: result_type = op.return_type @@ -91,11 +122,11 @@ def _custom_op_operate(expr, op, obj, reverse=False, result_type=None, result_type = type_api.BOOLEANTYPE return _binary_operate( - expr, op, obj, reverse=reverse, result_type=result_type, **kw) + expr, op, obj, reverse=reverse, result_type=result_type, **kw + ) -def _binary_operate(expr, op, obj, reverse=False, result_type=None, - **kw): +def _binary_operate(expr, op, obj, reverse=False, result_type=None, **kw): obj = _check_literal(expr, op, obj) if reverse: @@ -105,10 +136,10 @@ def _binary_operate(expr, op, obj, reverse=False, result_type=None, if result_type is None: op, result_type = left.comparator._adapt_expression( - op, right.comparator) + op, right.comparator + ) - return BinaryExpression( - left, right, op, type_=result_type, modifiers=kw) + return BinaryExpression(left, right, op, type_=result_type, modifiers=kw) def _conjunction_operate(expr, op, other, **kw): @@ -128,8 +159,7 @@ def _in_impl(expr, op, seq_or_selectable, negate_op, **kw): seq_or_selectable = _clause_element_as_expr(seq_or_selectable) if isinstance(seq_or_selectable, ScalarSelect): - return _boolean_compare(expr, op, seq_or_selectable, - negate=negate_op) + return _boolean_compare(expr, op, seq_or_selectable, negate=negate_op) elif isinstance(seq_or_selectable, SelectBase): # TODO: if we ever want to support (x, y, z) IN (select x, @@ -138,32 +168,33 @@ def _in_impl(expr, op, seq_or_selectable, negate_op, **kw): # does not export itself as a FROM clause return _boolean_compare( - expr, op, seq_or_selectable.as_scalar(), - negate=negate_op, **kw) + expr, op, seq_or_selectable.as_scalar(), negate=negate_op, **kw + ) elif isinstance(seq_or_selectable, (Selectable, TextClause)): - return _boolean_compare(expr, op, seq_or_selectable, - negate=negate_op, **kw) + return _boolean_compare( + expr, op, seq_or_selectable, negate=negate_op, **kw + ) elif isinstance(seq_or_selectable, ClauseElement): - if isinstance(seq_or_selectable, BindParameter) and \ - seq_or_selectable.expanding: + if ( + isinstance(seq_or_selectable, BindParameter) + and seq_or_selectable.expanding + ): if isinstance(expr, Tuple): - seq_or_selectable = ( - seq_or_selectable._with_expanding_in_types( - [elem.type for elem in expr] - ) + seq_or_selectable = seq_or_selectable._with_expanding_in_types( + [elem.type for elem in expr] ) return _boolean_compare( - expr, op, - seq_or_selectable, - negate=negate_op) + expr, op, seq_or_selectable, negate=negate_op + ) else: raise exc.InvalidRequestError( - 'in_() accepts' - ' either a list of expressions, ' + "in_() accepts" + " either a list of expressions, " 'a selectable, or an "expanding" bound parameter: %r' - % seq_or_selectable) + % seq_or_selectable + ) # Handle non selectable arguments as sequences args = [] @@ -171,9 +202,10 @@ def _in_impl(expr, op, seq_or_selectable, negate_op, **kw): if not _is_literal(o): if not isinstance(o, operators.ColumnOperators): raise exc.InvalidRequestError( - 'in_() accepts' - ' either a list of expressions, ' - 'a selectable, or an "expanding" bound parameter: %r' % o) + "in_() accepts" + " either a list of expressions, " + 'a selectable, or an "expanding" bound parameter: %r' % o + ) elif o is None: o = Null() else: @@ -182,15 +214,14 @@ def _in_impl(expr, op, seq_or_selectable, negate_op, **kw): if len(args) == 0: op, negate_op = ( - operators.empty_in_op, - operators.empty_notin_op) if op is operators.in_op \ - else ( - operators.empty_notin_op, - operators.empty_in_op) + (operators.empty_in_op, operators.empty_notin_op) + if op is operators.in_op + else (operators.empty_notin_op, operators.empty_in_op) + ) - return _boolean_compare(expr, op, - ClauseList(*args).self_group(against=op), - negate=negate_op) + return _boolean_compare( + expr, op, ClauseList(*args).self_group(against=op), negate=negate_op + ) def _getitem_impl(expr, op, other, **kw): @@ -202,13 +233,14 @@ def _getitem_impl(expr, op, other, **kw): def _unsupported_impl(expr, op, *arg, **kw): - raise NotImplementedError("Operator '%s' is not supported on " - "this expression" % op.__name__) + raise NotImplementedError( + "Operator '%s' is not supported on " "this expression" % op.__name__ + ) def _inv_impl(expr, op, **kw): """See :meth:`.ColumnOperators.__inv__`.""" - if hasattr(expr, 'negation_clause'): + if hasattr(expr, "negation_clause"): return expr.negation_clause else: return expr._negate() @@ -223,20 +255,22 @@ def _match_impl(expr, op, other, **kw): """See :meth:`.ColumnOperators.match`.""" return _boolean_compare( - expr, operators.match_op, - _check_literal( - expr, operators.match_op, other), + expr, + operators.match_op, + _check_literal(expr, operators.match_op, other), result_type=type_api.MATCHTYPE, negate=operators.notmatch_op - if op is operators.match_op else operators.match_op, + if op is operators.match_op + else operators.match_op, **kw ) def _distinct_impl(expr, op, **kw): """See :meth:`.ColumnOperators.distinct`.""" - return UnaryExpression(expr, operator=operators.distinct_op, - type_=expr.type) + return UnaryExpression( + expr, operator=operators.distinct_op, type_=expr.type + ) def _between_impl(expr, op, cleft, cright, **kw): @@ -247,17 +281,21 @@ def _between_impl(expr, op, cleft, cright, **kw): _check_literal(expr, operators.and_, cleft), _check_literal(expr, operators.and_, cright), operator=operators.and_, - group=False, group_contents=False), + group=False, + group_contents=False, + ), op, negate=operators.notbetween_op if op is operators.between_op else operators.between_op, - modifiers=kw) + modifiers=kw, + ) def _collate_impl(expr, op, other, **kw): return collate(expr, other) + # a mapping of operators with the method they use, along with # their negated operator for comparison operators operator_lookup = { @@ -271,8 +309,8 @@ operator_lookup = { "mod": (_binary_operate,), "truediv": (_binary_operate,), "custom_op": (_custom_op_operate,), - "json_path_getitem_op": (_binary_operate, ), - "json_getitem_op": (_binary_operate, ), + "json_path_getitem_op": (_binary_operate,), + "json_getitem_op": (_binary_operate,), "concat_op": (_binary_operate,), "any_op": (_scalar, CollectionAggregate._create_any), "all_op": (_scalar, CollectionAggregate._create_all), @@ -303,8 +341,8 @@ operator_lookup = { "match_op": (_match_impl,), "notmatch_op": (_match_impl,), "distinct_op": (_distinct_impl,), - "between_op": (_between_impl, ), - "notbetween_op": (_between_impl, ), + "between_op": (_between_impl,), + "notbetween_op": (_between_impl,), "neg": (_neg_impl,), "getitem": (_getitem_impl,), "lshift": (_unsupported_impl,), @@ -315,12 +353,11 @@ operator_lookup = { def _check_literal(expr, operator, other, bindparam_type=None): if isinstance(other, (ColumnElement, TextClause)): - if isinstance(other, BindParameter) and \ - other.type._isnull: + if isinstance(other, BindParameter) and other.type._isnull: other = other._clone() other.type = expr.type return other - elif hasattr(other, '__clause_element__'): + elif hasattr(other, "__clause_element__"): other = other.__clause_element__() elif isinstance(other, type_api.TypeEngine.Comparator): other = other.expr @@ -331,4 +368,3 @@ def _check_literal(expr, operator, other, bindparam_type=None): return expr._bind_param(operator, other, type_=bindparam_type) else: return other - |