123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014 |
- # sql/operators.py
- # Copyright (C) 2005-2017 the SQLAlchemy authors and contributors
- # <see AUTHORS file>
- #
- # This module is part of SQLAlchemy and is released under
- # the MIT License: http://www.opensource.org/licenses/mit-license.php
- # This module is part of SQLAlchemy and is released under
- # the MIT License: http://www.opensource.org/licenses/mit-license.php
- """Defines operators used in SQL expressions."""
- from .. import util
- from operator import (
- and_, or_, inv, add, mul, sub, mod, truediv, lt, le, ne, gt, ge, eq, neg,
- getitem, lshift, rshift, contains
- )
- if util.py2k:
- from operator import div
- else:
- div = truediv
- class Operators(object):
- """Base of comparison and logical operators.
- Implements base methods
- :meth:`~sqlalchemy.sql.operators.Operators.operate` and
- :meth:`~sqlalchemy.sql.operators.Operators.reverse_operate`, as well as
- :meth:`~sqlalchemy.sql.operators.Operators.__and__`,
- :meth:`~sqlalchemy.sql.operators.Operators.__or__`,
- :meth:`~sqlalchemy.sql.operators.Operators.__invert__`.
- Usually is used via its most common subclass
- :class:`.ColumnOperators`.
- """
- __slots__ = ()
- 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, precedence=0, is_comparison=False):
- """produce a generic operator function.
- e.g.::
- somecolumn.op("*")(5)
- produces::
- somecolumn * 5
- 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``.
- :param operator: a string which will be output as the infix operator
- between this element and the expression passed to the
- generated function.
- :param precedence: precedence to apply to the operator, when
- parenthesizing expressions. A lower number will cause the expression
- to be parenthesized when applied against another operator with
- higher precedence. The default value of ``0`` is lower than all
- operators except for the comma (``,``) and ``AS`` operators.
- A value of 100 will be higher or equal to all operators, and -100
- will be lower than or equal to all operators.
- .. versionadded:: 0.8 - added the 'precedence' argument.
- :param is_comparison: if True, the operator will be considered as a
- "comparison" operator, that is which evaluates to a boolean
- true/false value, like ``==``, ``>``, etc. This flag should be set
- so that ORM relationships can establish that the operator is a
- comparison operator when used in a custom join condition.
- .. versionadded:: 0.9.2 - added the
- :paramref:`.Operators.op.is_comparison` flag.
- .. seealso::
- :ref:`types_operators`
- :ref:`relationship_custom_operator`
- """
- operator = custom_op(opstring, precedence, is_comparison)
- def against(other):
- return operator(self, other)
- return against
- def operate(self, op, *other, **kwargs):
- r"""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 custom_op(object):
- """Represent a 'custom' operator.
- :class:`.custom_op` is normally instantitated 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.
- to represent the "factorial" operation::
- from sqlalchemy.sql import UnaryExpression
- from sqlalchemy.sql import operators
- from sqlalchemy import Numeric
- unary = UnaryExpression(table.c.somecolumn,
- modifier=operators.custom_op("!"),
- type_=Numeric)
- """
- __name__ = 'custom_op'
- def __init__(
- self, opstring, precedence=0, is_comparison=False,
- 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
- def __eq__(self, other):
- return isinstance(other, custom_op) and \
- other.opstring == self.opstring
- def __hash__(self):
- return id(self)
- def __call__(self, left, right, **kw):
- return left.operate(self, right, **kw)
- class ColumnOperators(Operators):
- """Defines boolean, comparison, and other operators for
- :class:`.ColumnElement` expressions.
- By default, all methods call down to
- :meth:`.operate` or :meth:`.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
- The core column expression unit :class:`.ColumnElement`
- overrides :meth:`.Operators.operate` and others
- to return further :class:`.ColumnElement` constructs,
- so that the ``==`` operation above is replaced by a clause
- construct.
- See also:
- :ref:`types_operators`
- :attr:`.TypeEngine.comparator_factory`
- :class:`.ColumnOperators`
- :class:`.PropComparator`
- """
- __slots__ = ()
- 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 is_distinct_from(self, other):
- """Implement the ``IS DISTINCT FROM`` operator.
- Renders "a IS DISTINCT FROM b" on most platforms;
- on some such as SQLite may render "a IS NOT b".
- .. versionadded:: 1.1
- """
- return self.operate(is_distinct_from, other)
- def isnot_distinct_from(self, other):
- """Implement the ``IS NOT DISTINCT FROM`` operator.
- Renders "a IS NOT DISTINCT FROM b" on most platforms;
- on some such as SQLite may render "a IS b".
- .. versionadded:: 1.1
- """
- return self.operate(isnot_distinct_from, 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 __contains__(self, other):
- return self.operate(contains, other)
- def __getitem__(self, index):
- """Implement the [] operator.
- This can be used by some database-specific types
- such as PostgreSQL ARRAY and HSTORE.
- """
- return self.operate(getitem, index)
- def __lshift__(self, other):
- """implement the << operator.
- Not used by SQLAlchemy core, this is provided
- for custom operator systems which want to use
- << as an extension point.
- """
- return self.operate(lshift, other)
- def __rshift__(self, other):
- """implement the >> operator.
- Not used by SQLAlchemy core, this is provided
- for custom operator systems which want to use
- >> as an extension point.
- """
- return self.operate(rshift, other)
- 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):
- r"""Implement the ``like`` operator.
- In a column context, produces the expression::
- a LIKE other
- E.g.::
- stmt = select([sometable]).\
- where(sometable.c.column.like("%foobar%"))
- :param other: expression to be compared
- :param escape: optional escape character, renders the ``ESCAPE``
- keyword, e.g.::
- somecolumn.like("foo/%bar", escape="/")
- .. seealso::
- :meth:`.ColumnOperators.ilike`
- """
- return self.operate(like_op, other, escape=escape)
- def ilike(self, other, escape=None):
- r"""Implement the ``ilike`` operator, e.g. case insensitive LIKE.
- In a column context, produces an expression either of the form::
- lower(a) LIKE lower(other)
- Or on backends that support the ILIKE operator::
- a ILIKE other
- E.g.::
- stmt = select([sometable]).\
- where(sometable.c.column.ilike("%foobar%"))
- :param other: expression to be compared
- :param escape: optional escape character, renders the ``ESCAPE``
- keyword, e.g.::
- somecolumn.ilike("foo/%bar", escape="/")
- .. seealso::
- :meth:`.ColumnOperators.like`
- """
- 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 notin_(self, other):
- """implement the ``NOT IN`` operator.
- This is equivalent to using negation with
- :meth:`.ColumnOperators.in_`, i.e. ``~x.in_(y)``.
- .. versionadded:: 0.8
- .. seealso::
- :meth:`.ColumnOperators.in_`
- """
- return self.operate(notin_op, other)
- def notlike(self, other, escape=None):
- """implement the ``NOT LIKE`` operator.
- This is equivalent to using negation with
- :meth:`.ColumnOperators.like`, i.e. ``~x.like(y)``.
- .. versionadded:: 0.8
- .. seealso::
- :meth:`.ColumnOperators.like`
- """
- return self.operate(notlike_op, other, escape=escape)
- def notilike(self, other, escape=None):
- """implement the ``NOT ILIKE`` operator.
- This is equivalent to using negation with
- :meth:`.ColumnOperators.ilike`, i.e. ``~x.ilike(y)``.
- .. versionadded:: 0.8
- .. seealso::
- :meth:`.ColumnOperators.ilike`
- """
- return self.operate(notilike_op, other, escape=escape)
- def is_(self, other):
- """Implement the ``IS`` operator.
- Normally, ``IS`` is generated automatically when comparing to a
- value of ``None``, which resolves to ``NULL``. However, explicit
- usage of ``IS`` may be desirable if comparing to boolean values
- on certain platforms.
- .. versionadded:: 0.7.9
- .. seealso:: :meth:`.ColumnOperators.isnot`
- """
- return self.operate(is_, other)
- def isnot(self, other):
- """Implement the ``IS NOT`` operator.
- Normally, ``IS NOT`` is generated automatically when comparing to a
- value of ``None``, which resolves to ``NULL``. However, explicit
- usage of ``IS NOT`` may be desirable if comparing to boolean values
- on certain platforms.
- .. versionadded:: 0.7.9
- .. seealso:: :meth:`.ColumnOperators.is_`
- """
- return self.operate(isnot, other)
- def startswith(self, other, **kwargs):
- """Implement the ``startwith`` operator.
- In a column context, produces the clause ``LIKE '<other>%'``
- """
- return self.operate(startswith_op, other, **kwargs)
- def endswith(self, other, **kwargs):
- """Implement the 'endswith' operator.
- In a column context, produces the clause ``LIKE '%<other>'``
- """
- return self.operate(endswith_op, other, **kwargs)
- def contains(self, other, **kwargs):
- """Implement the 'contains' operator.
- In a column context, produces the clause ``LIKE '%<other>%'``
- """
- return self.operate(contains_op, other, **kwargs)
- def match(self, other, **kwargs):
- """Implements a database-specific 'match' operator.
- :meth:`~.ColumnOperators.match` attempts to resolve to
- a MATCH-like function or operator provided by the backend.
- Examples include:
- * PostgreSQL - renders ``x @@ to_tsquery(y)``
- * MySQL - renders ``MATCH (x) AGAINST (y IN BOOLEAN MODE)``
- * Oracle - renders ``CONTAINS(x, y)``
- * other backends may provide special implementations.
- * Backends without any special implementation will emit
- the operator as "MATCH". This is compatible with SQlite, for
- example.
- """
- 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:`.ColumnOperators.__add__`.
- """
- return self.reverse_operate(add, other)
- def __rsub__(self, other):
- """Implement the ``-`` operator in reverse.
- See :meth:`.ColumnOperators.__sub__`.
- """
- return self.reverse_operate(sub, other)
- def __rmul__(self, other):
- """Implement the ``*`` operator in reverse.
- See :meth:`.ColumnOperators.__mul__`.
- """
- return self.reverse_operate(mul, other)
- def __rdiv__(self, other):
- """Implement the ``/`` operator in reverse.
- See :meth:`.ColumnOperators.__div__`.
- """
- return self.reverse_operate(div, other)
- def __rmod__(self, other):
- """Implement the ``%`` operator in reverse.
- See :meth:`.ColumnOperators.__mod__`.
- """
- return self.reverse_operate(mod, other)
- def between(self, cleft, cright, symmetric=False):
- """Produce a :func:`~.expression.between` clause against
- the parent object, given the lower and upper range.
- """
- return self.operate(between_op, cleft, cright, symmetric=symmetric)
- def distinct(self):
- """Produce a :func:`~.expression.distinct` clause against the
- parent object.
- """
- return self.operate(distinct_op)
- def any_(self):
- """Produce a :func:`~.expression.any_` clause against the
- parent object.
- .. versionadded:: 1.1
- """
- return self.operate(any_op)
- def all_(self):
- """Produce a :func:`~.expression.all_` clause against the
- parent object.
- .. versionadded:: 1.1
- """
- return self.operate(all_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:`.ColumnOperators.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:`.ColumnOperators.__truediv__`.
- """
- return self.reverse_operate(truediv, other)
- def from_():
- raise NotImplementedError()
- def as_():
- raise NotImplementedError()
- def exists():
- raise NotImplementedError()
- def istrue(a):
- raise NotImplementedError()
- def isfalse(a):
- raise NotImplementedError()
- def is_distinct_from(a, b):
- return a.is_distinct_from(b)
- def isnot_distinct_from(a, b):
- return a.isnot_distinct_from(b)
- def is_(a, b):
- return a.is_(b)
- def isnot(a, b):
- return a.isnot(b)
- def collate(a, b):
- return a.collate(b)
- def op(a, opstring, b):
- return a.op(opstring)(b)
- def like_op(a, b, escape=None):
- return a.like(b, escape=escape)
- def notlike_op(a, b, escape=None):
- return a.notlike(b, escape=escape)
- def ilike_op(a, b, escape=None):
- return a.ilike(b, escape=escape)
- def notilike_op(a, b, escape=None):
- return a.notilike(b, escape=escape)
- def between_op(a, b, c, symmetric=False):
- return a.between(b, c, symmetric=symmetric)
- def notbetween_op(a, b, c, symmetric=False):
- return a.notbetween(b, c, symmetric=symmetric)
- def in_op(a, b):
- return a.in_(b)
- def notin_op(a, b):
- return a.notin_(b)
- def distinct_op(a):
- return a.distinct()
- def any_op(a):
- return a.any_()
- def all_op(a):
- return a.all_()
- def startswith_op(a, b, escape=None):
- return a.startswith(b, escape=escape)
- def notstartswith_op(a, b, escape=None):
- return ~a.startswith(b, escape=escape)
- def endswith_op(a, b, escape=None):
- return a.endswith(b, escape=escape)
- def notendswith_op(a, b, escape=None):
- return ~a.endswith(b, escape=escape)
- def contains_op(a, b, escape=None):
- return a.contains(b, escape=escape)
- def notcontains_op(a, b, escape=None):
- return ~a.contains(b, escape=escape)
- def match_op(a, b, **kw):
- return a.match(b, **kw)
- def notmatch_op(a, b, **kw):
- return a.notmatch(b, **kw)
- def comma_op(a, b):
- raise NotImplementedError()
- def concat_op(a, b):
- return a.concat(b)
- def desc_op(a):
- return a.desc()
- def asc_op(a):
- return a.asc()
- def nullsfirst_op(a):
- return a.nullsfirst()
- def nullslast_op(a):
- return a.nullslast()
- def json_getitem_op(a, b):
- raise NotImplementedError()
- def json_path_getitem_op(a, b):
- raise NotImplementedError()
- _commutative = set([eq, ne, add, mul])
- _comparison = set([eq, ne, lt, gt, ge, le, between_op, like_op])
- def is_comparison(op):
- return op in _comparison or \
- isinstance(op, custom_op) and op.is_comparison
- def is_commutative(op):
- return op in _commutative
- def is_ordering_modifier(op):
- return op in (asc_op, desc_op,
- nullsfirst_op, nullslast_op)
- def is_natural_self_precedent(op):
- return op in _natural_self_precedent or \
- isinstance(op, custom_op) and op.natural_self_precedent
- _mirror = {
- gt: lt,
- ge: le,
- lt: gt,
- le: ge
- }
- def mirror(op):
- """rotate a comparison operator 180 degrees.
- Note this is not the same as negation.
- """
- return _mirror.get(op, op)
- _associative = _commutative.union([concat_op, and_, or_]).difference([eq, ne])
- _natural_self_precedent = _associative.union([
- getitem, json_getitem_op, json_path_getitem_op])
- """Operators where if we have (a op b) op c, we don't want to
- parenthesize (a op b).
- """
- _asbool = util.symbol('_asbool', canonical=-10)
- _smallest = util.symbol('_smallest', canonical=-100)
- _largest = util.symbol('_largest', canonical=100)
- _PRECEDENCE = {
- from_: 15,
- any_op: 15,
- all_op: 15,
- getitem: 15,
- json_getitem_op: 15,
- json_path_getitem_op: 15,
- mul: 8,
- truediv: 8,
- div: 8,
- mod: 8,
- neg: 8,
- add: 7,
- sub: 7,
- concat_op: 6,
- match_op: 6,
- notmatch_op: 6,
- ilike_op: 6,
- notilike_op: 6,
- like_op: 6,
- notlike_op: 6,
- in_op: 6,
- notin_op: 6,
- is_: 6,
- isnot: 6,
- eq: 5,
- ne: 5,
- is_distinct_from: 5,
- isnot_distinct_from: 5,
- gt: 5,
- lt: 5,
- ge: 5,
- le: 5,
- between_op: 5,
- notbetween_op: 5,
- distinct_op: 5,
- inv: 5,
- istrue: 5,
- isfalse: 5,
- and_: 3,
- or_: 2,
- comma_op: -1,
- desc_op: 3,
- asc_op: 3,
- collate: 4,
- as_: -1,
- exists: 0,
- _asbool: -10,
- _smallest: _smallest,
- _largest: _largest
- }
- def is_precedent(operator, against):
- if operator is against and is_natural_self_precedent(operator):
- return False
- else:
- return (_PRECEDENCE.get(operator,
- getattr(operator, 'precedence', _smallest)) <=
- _PRECEDENCE.get(against,
- getattr(against, 'precedence', _largest)))
|