main commit
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-10-16 16:30:25 +09:00
parent 91c7e04474
commit 537e7b363f
1146 changed files with 45926 additions and 77196 deletions

View File

@@ -1,5 +1,5 @@
# sql/operators.py
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
# Copyright (C) 2005-2023 the SQLAlchemy authors and contributors
# <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
@@ -77,7 +77,8 @@ class OperatorType(Protocol):
right: Optional[Any] = None,
*other: Any,
**kwargs: Any,
) -> ColumnElement[Any]: ...
) -> ColumnElement[Any]:
...
@overload
def __call__(
@@ -86,7 +87,8 @@ class OperatorType(Protocol):
right: Optional[Any] = None,
*other: Any,
**kwargs: Any,
) -> Operators: ...
) -> Operators:
...
def __call__(
self,
@@ -94,7 +96,8 @@ class OperatorType(Protocol):
right: Optional[Any] = None,
*other: Any,
**kwargs: Any,
) -> Operators: ...
) -> Operators:
...
add = cast(OperatorType, _uncast_add)
@@ -148,7 +151,6 @@ class Operators:
is equivalent to::
from sqlalchemy import and_
and_(a, b)
Care should be taken when using ``&`` regarding
@@ -173,7 +175,6 @@ class Operators:
is equivalent to::
from sqlalchemy import or_
or_(a, b)
Care should be taken when using ``|`` regarding
@@ -198,7 +199,6 @@ class Operators:
is equivalent to::
from sqlalchemy import not_
not_(a)
"""
@@ -227,7 +227,7 @@ class Operators:
This function can also be used to make bitwise operators explicit. For
example::
somecolumn.op("&")(0xFF)
somecolumn.op('&')(0xff)
is a bitwise AND of the value in ``somecolumn``.
@@ -278,7 +278,7 @@ class Operators:
e.g.::
>>> expr = column("x").op("+", python_impl=lambda a, b: a + b)("y")
>>> expr = column('x').op('+', python_impl=lambda a, b: a + b)('y')
The operator for the above expression will also work for non-SQL
left and right objects::
@@ -392,9 +392,10 @@ class custom_op(OperatorType, Generic[_T]):
from sqlalchemy.sql import operators
from sqlalchemy import Numeric
unary = UnaryExpression(
table.c.somecolumn, modifier=operators.custom_op("!"), type_=Numeric
)
unary = UnaryExpression(table.c.somecolumn,
modifier=operators.custom_op("!"),
type_=Numeric)
.. seealso::
@@ -402,7 +403,7 @@ class custom_op(OperatorType, Generic[_T]):
:meth:`.Operators.bool_op`
""" # noqa: E501
"""
__name__ = "custom_op"
@@ -465,7 +466,8 @@ class custom_op(OperatorType, Generic[_T]):
right: Optional[Any] = None,
*other: Any,
**kwargs: Any,
) -> ColumnElement[Any]: ...
) -> ColumnElement[Any]:
...
@overload
def __call__(
@@ -474,7 +476,8 @@ class custom_op(OperatorType, Generic[_T]):
right: Optional[Any] = None,
*other: Any,
**kwargs: Any,
) -> Operators: ...
) -> Operators:
...
def __call__(
self,
@@ -542,11 +545,13 @@ class ColumnOperators(Operators):
def operate(
self, op: OperatorType, *other: Any, **kwargs: Any
) -> ColumnOperators: ...
) -> ColumnOperators:
...
def reverse_operate(
self, op: OperatorType, other: Any, **kwargs: Any
) -> ColumnOperators: ...
) -> ColumnOperators:
...
def __lt__(self, other: Any) -> ColumnOperators:
"""Implement the ``<`` operator.
@@ -569,7 +574,8 @@ class ColumnOperators(Operators):
# https://docs.python.org/3/reference/datamodel.html#object.__hash__
if TYPE_CHECKING:
def __hash__(self) -> int: ...
def __hash__(self) -> int:
...
else:
__hash__ = Operators.__hash__
@@ -617,7 +623,8 @@ class ColumnOperators(Operators):
# deprecated 1.4; see #5435
if TYPE_CHECKING:
def isnot_distinct_from(self, other: Any) -> ColumnOperators: ...
def isnot_distinct_from(self, other: Any) -> ColumnOperators:
...
else:
isnot_distinct_from = is_not_distinct_from
@@ -700,15 +707,14 @@ class ColumnOperators(Operators):
) -> ColumnOperators:
r"""Implement the ``like`` operator.
In a column context, produces the expression:
.. sourcecode:: sql
In a column context, produces the expression::
a LIKE other
E.g.::
stmt = select(sometable).where(sometable.c.column.like("%foobar%"))
stmt = select(sometable).\
where(sometable.c.column.like("%foobar%"))
:param other: expression to be compared
:param escape: optional escape character, renders the ``ESCAPE``
@@ -728,21 +734,18 @@ class ColumnOperators(Operators):
) -> ColumnOperators:
r"""Implement the ``ilike`` operator, e.g. case insensitive LIKE.
In a column context, produces an expression either of the form:
.. sourcecode:: sql
In a column context, produces an expression either of the form::
lower(a) LIKE lower(other)
Or on backends that support the ILIKE operator:
.. sourcecode:: sql
Or on backends that support the ILIKE operator::
a ILIKE other
E.g.::
stmt = select(sometable).where(sometable.c.column.ilike("%foobar%"))
stmt = select(sometable).\
where(sometable.c.column.ilike("%foobar%"))
:param other: expression to be compared
:param escape: optional escape character, renders the ``ESCAPE``
@@ -754,7 +757,7 @@ class ColumnOperators(Operators):
:meth:`.ColumnOperators.like`
""" # noqa: E501
"""
return self.operate(ilike_op, other, escape=escape)
def bitwise_xor(self, other: Any) -> ColumnOperators:
@@ -848,15 +851,12 @@ class ColumnOperators(Operators):
The given parameter ``other`` may be:
* A list of literal values,
e.g.::
* A list of literal values, e.g.::
stmt.where(column.in_([1, 2, 3]))
In this calling form, the list of items is converted to a set of
bound parameters the same length as the list given:
.. sourcecode:: sql
bound parameters the same length as the list given::
WHERE COL IN (?, ?, ?)
@@ -864,20 +864,16 @@ class ColumnOperators(Operators):
:func:`.tuple_` containing multiple expressions::
from sqlalchemy import tuple_
stmt.where(tuple_(col1, col2).in_([(1, 10), (2, 20), (3, 30)]))
* An empty list,
e.g.::
* An empty list, e.g.::
stmt.where(column.in_([]))
In this calling form, the expression renders an "empty set"
expression. These expressions are tailored to individual backends
and are generally trying to get an empty SELECT statement as a
subquery. Such as on SQLite, the expression is:
.. sourcecode:: sql
subquery. Such as on SQLite, the expression is::
WHERE col IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1)
@@ -887,12 +883,10 @@ class ColumnOperators(Operators):
* A bound parameter, e.g. :func:`.bindparam`, may be used if it
includes the :paramref:`.bindparam.expanding` flag::
stmt.where(column.in_(bindparam("value", expanding=True)))
stmt.where(column.in_(bindparam('value', expanding=True)))
In this calling form, the expression renders a special non-SQL
placeholder expression that looks like:
.. sourcecode:: sql
placeholder expression that looks like::
WHERE COL IN ([EXPANDING_value])
@@ -902,9 +896,7 @@ class ColumnOperators(Operators):
connection.execute(stmt, {"value": [1, 2, 3]})
The database would be passed a bound parameter for each value:
.. sourcecode:: sql
The database would be passed a bound parameter for each value::
WHERE COL IN (?, ?, ?)
@@ -912,9 +904,7 @@ class ColumnOperators(Operators):
If an empty list is passed, a special "empty list" expression,
which is specific to the database in use, is rendered. On
SQLite this would be:
.. sourcecode:: sql
SQLite this would be::
WHERE COL IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1)
@@ -925,12 +915,13 @@ class ColumnOperators(Operators):
correlated scalar select::
stmt.where(
column.in_(select(othertable.c.y).where(table.c.x == othertable.c.x))
column.in_(
select(othertable.c.y).
where(table.c.x == othertable.c.x)
)
)
In this calling form, :meth:`.ColumnOperators.in_` renders as given:
.. sourcecode:: sql
In this calling form, :meth:`.ColumnOperators.in_` renders as given::
WHERE COL IN (SELECT othertable.y
FROM othertable WHERE othertable.x = table.x)
@@ -939,7 +930,7 @@ class ColumnOperators(Operators):
construct, or a :func:`.bindparam` construct that includes the
:paramref:`.bindparam.expanding` flag set to True.
""" # noqa: E501
"""
return self.operate(in_op, other)
def not_in(self, other: Any) -> ColumnOperators:
@@ -973,7 +964,8 @@ class ColumnOperators(Operators):
# deprecated 1.4; see #5429
if TYPE_CHECKING:
def notin_(self, other: Any) -> ColumnOperators: ...
def notin_(self, other: Any) -> ColumnOperators:
...
else:
notin_ = not_in
@@ -1002,7 +994,8 @@ class ColumnOperators(Operators):
def notlike(
self, other: Any, escape: Optional[str] = None
) -> ColumnOperators: ...
) -> ColumnOperators:
...
else:
notlike = not_like
@@ -1031,7 +1024,8 @@ class ColumnOperators(Operators):
def notilike(
self, other: Any, escape: Optional[str] = None
) -> ColumnOperators: ...
) -> ColumnOperators:
...
else:
notilike = not_ilike
@@ -1069,7 +1063,8 @@ class ColumnOperators(Operators):
# deprecated 1.4; see #5429
if TYPE_CHECKING:
def isnot(self, other: Any) -> ColumnOperators: ...
def isnot(self, other: Any) -> ColumnOperators:
...
else:
isnot = is_not
@@ -1083,15 +1078,14 @@ class ColumnOperators(Operators):
r"""Implement the ``startswith`` operator.
Produces a LIKE expression that tests against a match for the start
of a string value:
.. sourcecode:: sql
of a string value::
column LIKE <other> || '%'
E.g.::
stmt = select(sometable).where(sometable.c.column.startswith("foobar"))
stmt = select(sometable).\
where(sometable.c.column.startswith("foobar"))
Since the operator uses ``LIKE``, wildcard characters
``"%"`` and ``"_"`` that are present inside the <other> expression
@@ -1120,9 +1114,7 @@ class ColumnOperators(Operators):
somecolumn.startswith("foo%bar", autoescape=True)
Will render as:
.. sourcecode:: sql
Will render as::
somecolumn LIKE :param || '%' ESCAPE '/'
@@ -1138,9 +1130,7 @@ class ColumnOperators(Operators):
somecolumn.startswith("foo/%bar", escape="^")
Will render as:
.. sourcecode:: sql
Will render as::
somecolumn LIKE :param || '%' ESCAPE '^'
@@ -1160,7 +1150,7 @@ class ColumnOperators(Operators):
:meth:`.ColumnOperators.like`
""" # noqa: E501
"""
return self.operate(
startswith_op, other, escape=escape, autoescape=autoescape
)
@@ -1175,15 +1165,14 @@ class ColumnOperators(Operators):
version of :meth:`.ColumnOperators.startswith`.
Produces a LIKE expression that tests against an insensitive
match for the start of a string value:
.. sourcecode:: sql
match for the start of a string value::
lower(column) LIKE lower(<other>) || '%'
E.g.::
stmt = select(sometable).where(sometable.c.column.istartswith("foobar"))
stmt = select(sometable).\
where(sometable.c.column.istartswith("foobar"))
Since the operator uses ``LIKE``, wildcard characters
``"%"`` and ``"_"`` that are present inside the <other> expression
@@ -1212,9 +1201,7 @@ class ColumnOperators(Operators):
somecolumn.istartswith("foo%bar", autoescape=True)
Will render as:
.. sourcecode:: sql
Will render as::
lower(somecolumn) LIKE lower(:param) || '%' ESCAPE '/'
@@ -1230,9 +1217,7 @@ class ColumnOperators(Operators):
somecolumn.istartswith("foo/%bar", escape="^")
Will render as:
.. sourcecode:: sql
Will render as::
lower(somecolumn) LIKE lower(:param) || '%' ESCAPE '^'
@@ -1247,7 +1232,7 @@ class ColumnOperators(Operators):
.. seealso::
:meth:`.ColumnOperators.startswith`
""" # noqa: E501
"""
return self.operate(
istartswith_op, other, escape=escape, autoescape=autoescape
)
@@ -1261,15 +1246,14 @@ class ColumnOperators(Operators):
r"""Implement the 'endswith' operator.
Produces a LIKE expression that tests against a match for the end
of a string value:
.. sourcecode:: sql
of a string value::
column LIKE '%' || <other>
E.g.::
stmt = select(sometable).where(sometable.c.column.endswith("foobar"))
stmt = select(sometable).\
where(sometable.c.column.endswith("foobar"))
Since the operator uses ``LIKE``, wildcard characters
``"%"`` and ``"_"`` that are present inside the <other> expression
@@ -1298,9 +1282,7 @@ class ColumnOperators(Operators):
somecolumn.endswith("foo%bar", autoescape=True)
Will render as:
.. sourcecode:: sql
Will render as::
somecolumn LIKE '%' || :param ESCAPE '/'
@@ -1316,9 +1298,7 @@ class ColumnOperators(Operators):
somecolumn.endswith("foo/%bar", escape="^")
Will render as:
.. sourcecode:: sql
Will render as::
somecolumn LIKE '%' || :param ESCAPE '^'
@@ -1338,7 +1318,7 @@ class ColumnOperators(Operators):
:meth:`.ColumnOperators.like`
""" # noqa: E501
"""
return self.operate(
endswith_op, other, escape=escape, autoescape=autoescape
)
@@ -1353,15 +1333,14 @@ class ColumnOperators(Operators):
version of :meth:`.ColumnOperators.endswith`.
Produces a LIKE expression that tests against an insensitive match
for the end of a string value:
.. sourcecode:: sql
for the end of a string value::
lower(column) LIKE '%' || lower(<other>)
E.g.::
stmt = select(sometable).where(sometable.c.column.iendswith("foobar"))
stmt = select(sometable).\
where(sometable.c.column.iendswith("foobar"))
Since the operator uses ``LIKE``, wildcard characters
``"%"`` and ``"_"`` that are present inside the <other> expression
@@ -1390,9 +1369,7 @@ class ColumnOperators(Operators):
somecolumn.iendswith("foo%bar", autoescape=True)
Will render as:
.. sourcecode:: sql
Will render as::
lower(somecolumn) LIKE '%' || lower(:param) ESCAPE '/'
@@ -1408,9 +1385,7 @@ class ColumnOperators(Operators):
somecolumn.iendswith("foo/%bar", escape="^")
Will render as:
.. sourcecode:: sql
Will render as::
lower(somecolumn) LIKE '%' || lower(:param) ESCAPE '^'
@@ -1425,7 +1400,7 @@ class ColumnOperators(Operators):
.. seealso::
:meth:`.ColumnOperators.endswith`
""" # noqa: E501
"""
return self.operate(
iendswith_op, other, escape=escape, autoescape=autoescape
)
@@ -1434,15 +1409,14 @@ class ColumnOperators(Operators):
r"""Implement the 'contains' operator.
Produces a LIKE expression that tests against a match for the middle
of a string value:
.. sourcecode:: sql
of a string value::
column LIKE '%' || <other> || '%'
E.g.::
stmt = select(sometable).where(sometable.c.column.contains("foobar"))
stmt = select(sometable).\
where(sometable.c.column.contains("foobar"))
Since the operator uses ``LIKE``, wildcard characters
``"%"`` and ``"_"`` that are present inside the <other> expression
@@ -1471,9 +1445,7 @@ class ColumnOperators(Operators):
somecolumn.contains("foo%bar", autoescape=True)
Will render as:
.. sourcecode:: sql
Will render as::
somecolumn LIKE '%' || :param || '%' ESCAPE '/'
@@ -1489,9 +1461,7 @@ class ColumnOperators(Operators):
somecolumn.contains("foo/%bar", escape="^")
Will render as:
.. sourcecode:: sql
Will render as::
somecolumn LIKE '%' || :param || '%' ESCAPE '^'
@@ -1512,7 +1482,7 @@ class ColumnOperators(Operators):
:meth:`.ColumnOperators.like`
""" # noqa: E501
"""
return self.operate(contains_op, other, **kw)
def icontains(self, other: Any, **kw: Any) -> ColumnOperators:
@@ -1520,15 +1490,14 @@ class ColumnOperators(Operators):
version of :meth:`.ColumnOperators.contains`.
Produces a LIKE expression that tests against an insensitive match
for the middle of a string value:
.. sourcecode:: sql
for the middle of a string value::
lower(column) LIKE '%' || lower(<other>) || '%'
E.g.::
stmt = select(sometable).where(sometable.c.column.icontains("foobar"))
stmt = select(sometable).\
where(sometable.c.column.icontains("foobar"))
Since the operator uses ``LIKE``, wildcard characters
``"%"`` and ``"_"`` that are present inside the <other> expression
@@ -1557,9 +1526,7 @@ class ColumnOperators(Operators):
somecolumn.icontains("foo%bar", autoescape=True)
Will render as:
.. sourcecode:: sql
Will render as::
lower(somecolumn) LIKE '%' || lower(:param) || '%' ESCAPE '/'
@@ -1575,9 +1542,7 @@ class ColumnOperators(Operators):
somecolumn.icontains("foo/%bar", escape="^")
Will render as:
.. sourcecode:: sql
Will render as::
lower(somecolumn) LIKE '%' || lower(:param) || '%' ESCAPE '^'
@@ -1593,7 +1558,7 @@ class ColumnOperators(Operators):
:meth:`.ColumnOperators.contains`
""" # noqa: E501
"""
return self.operate(icontains_op, other, **kw)
def match(self, other: Any, **kwargs: Any) -> ColumnOperators:
@@ -1617,7 +1582,7 @@ class ColumnOperators(Operators):
:class:`_mysql.match` - MySQL specific construct with
additional features.
* Oracle Database - renders ``CONTAINS(x, y)``
* 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
@@ -1634,7 +1599,7 @@ class ColumnOperators(Operators):
E.g.::
stmt = select(table.c.some_column).where(
table.c.some_column.regexp_match("^(b|c)")
table.c.some_column.regexp_match('^(b|c)')
)
:meth:`_sql.ColumnOperators.regexp_match` attempts to resolve to
@@ -1645,7 +1610,7 @@ class ColumnOperators(Operators):
Examples include:
* PostgreSQL - renders ``x ~ y`` or ``x !~ y`` when negated.
* Oracle Database - renders ``REGEXP_LIKE(x, y)``
* Oracle - renders ``REGEXP_LIKE(x, y)``
* SQLite - uses SQLite's ``REGEXP`` placeholder operator and calls into
the Python ``re.match()`` builtin.
* other backends may provide special implementations.
@@ -1653,9 +1618,9 @@ class ColumnOperators(Operators):
the operator as "REGEXP" or "NOT REGEXP". This is compatible with
SQLite and MySQL, for example.
Regular expression support is currently implemented for Oracle
Database, PostgreSQL, MySQL and MariaDB. Partial support is available
for SQLite. Support among third-party dialects may vary.
Regular expression support is currently implemented for Oracle,
PostgreSQL, MySQL and MariaDB. Partial support is available for
SQLite. Support among third-party dialects may vary.
:param pattern: The regular expression pattern string or column
clause.
@@ -1692,7 +1657,11 @@ class ColumnOperators(Operators):
E.g.::
stmt = select(
table.c.some_column.regexp_replace("b(..)", "X\1Y", flags="g")
table.c.some_column.regexp_replace(
'b(..)',
'X\1Y',
flags='g'
)
)
:meth:`_sql.ColumnOperators.regexp_replace` attempts to resolve to
@@ -1702,8 +1671,8 @@ class ColumnOperators(Operators):
**not backend agnostic**.
Regular expression replacement support is currently implemented for
Oracle Database, PostgreSQL, MySQL 8 or greater and MariaDB. Support
among third-party dialects may vary.
Oracle, PostgreSQL, MySQL 8 or greater and MariaDB. Support among
third-party dialects may vary.
:param pattern: The regular expression pattern string or column
clause.
@@ -1759,7 +1728,8 @@ class ColumnOperators(Operators):
# deprecated 1.4; see #5435
if TYPE_CHECKING:
def nullsfirst(self) -> ColumnOperators: ...
def nullsfirst(self) -> ColumnOperators:
...
else:
nullsfirst = nulls_first
@@ -1777,7 +1747,8 @@ class ColumnOperators(Operators):
# deprecated 1.4; see #5429
if TYPE_CHECKING:
def nullslast(self) -> ColumnOperators: ...
def nullslast(self) -> ColumnOperators:
...
else:
nullslast = nulls_last
@@ -1848,10 +1819,10 @@ class ColumnOperators(Operators):
See the documentation for :func:`_sql.any_` for examples.
.. note:: be sure to not confuse the newer
:meth:`_sql.ColumnOperators.any_` method with the **legacy**
version of this method, the :meth:`_types.ARRAY.Comparator.any`
method that's specific to :class:`_types.ARRAY`, which uses a
different calling style.
:meth:`_sql.ColumnOperators.any_` method with its older
:class:`_types.ARRAY`-specific counterpart, the
:meth:`_types.ARRAY.Comparator.any` method, which a different
calling syntax and usage pattern.
"""
return self.operate(any_op)
@@ -1863,10 +1834,10 @@ class ColumnOperators(Operators):
See the documentation for :func:`_sql.all_` for examples.
.. note:: be sure to not confuse the newer
:meth:`_sql.ColumnOperators.all_` method with the **legacy**
version of this method, the :meth:`_types.ARRAY.Comparator.all`
method that's specific to :class:`_types.ARRAY`, which uses a
different calling style.
:meth:`_sql.ColumnOperators.all_` method with its older
:class:`_types.ARRAY`-specific counterpart, the
:meth:`_types.ARRAY.Comparator.all` method, which a different
calling syntax and usage pattern.
"""
return self.operate(all_op)
@@ -1997,7 +1968,8 @@ def is_true(a: Any) -> Any:
if TYPE_CHECKING:
@_operator_fn
def istrue(a: Any) -> Any: ...
def istrue(a: Any) -> Any:
...
else:
istrue = is_true
@@ -2012,7 +1984,8 @@ def is_false(a: Any) -> Any:
if TYPE_CHECKING:
@_operator_fn
def isfalse(a: Any) -> Any: ...
def isfalse(a: Any) -> Any:
...
else:
isfalse = is_false
@@ -2034,7 +2007,8 @@ def is_not_distinct_from(a: Any, b: Any) -> Any:
if TYPE_CHECKING:
@_operator_fn
def isnot_distinct_from(a: Any, b: Any) -> Any: ...
def isnot_distinct_from(a: Any, b: Any) -> Any:
...
else:
isnot_distinct_from = is_not_distinct_from
@@ -2056,7 +2030,8 @@ def is_not(a: Any, b: Any) -> Any:
if TYPE_CHECKING:
@_operator_fn
def isnot(a: Any, b: Any) -> Any: ...
def isnot(a: Any, b: Any) -> Any:
...
else:
isnot = is_not
@@ -2088,7 +2063,8 @@ def not_like_op(a: Any, b: Any, escape: Optional[str] = None) -> Any:
if TYPE_CHECKING:
@_operator_fn
def notlike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any: ...
def notlike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any:
...
else:
notlike_op = not_like_op
@@ -2110,7 +2086,8 @@ def not_ilike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any:
if TYPE_CHECKING:
@_operator_fn
def notilike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any: ...
def notilike_op(a: Any, b: Any, escape: Optional[str] = None) -> Any:
...
else:
notilike_op = not_ilike_op
@@ -2132,9 +2109,8 @@ def not_between_op(a: Any, b: Any, c: Any, symmetric: bool = False) -> Any:
if TYPE_CHECKING:
@_operator_fn
def notbetween_op(
a: Any, b: Any, c: Any, symmetric: bool = False
) -> Any: ...
def notbetween_op(a: Any, b: Any, c: Any, symmetric: bool = False) -> Any:
...
else:
notbetween_op = not_between_op
@@ -2156,7 +2132,8 @@ def not_in_op(a: Any, b: Any) -> Any:
if TYPE_CHECKING:
@_operator_fn
def notin_op(a: Any, b: Any) -> Any: ...
def notin_op(a: Any, b: Any) -> Any:
...
else:
notin_op = not_in_op
@@ -2221,7 +2198,8 @@ if TYPE_CHECKING:
@_operator_fn
def notstartswith_op(
a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False
) -> Any: ...
) -> Any:
...
else:
notstartswith_op = not_startswith_op
@@ -2265,7 +2243,8 @@ if TYPE_CHECKING:
@_operator_fn
def notendswith_op(
a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False
) -> Any: ...
) -> Any:
...
else:
notendswith_op = not_endswith_op
@@ -2309,7 +2288,8 @@ if TYPE_CHECKING:
@_operator_fn
def notcontains_op(
a: Any, b: Any, escape: Optional[str] = None, autoescape: bool = False
) -> Any: ...
) -> Any:
...
else:
notcontains_op = not_contains_op
@@ -2366,7 +2346,8 @@ def not_match_op(a: Any, b: Any, **kw: Any) -> Any:
if TYPE_CHECKING:
@_operator_fn
def notmatch_op(a: Any, b: Any, **kw: Any) -> Any: ...
def notmatch_op(a: Any, b: Any, **kw: Any) -> Any:
...
else:
notmatch_op = not_match_op
@@ -2411,7 +2392,8 @@ def nulls_first_op(a: Any) -> Any:
if TYPE_CHECKING:
@_operator_fn
def nullsfirst_op(a: Any) -> Any: ...
def nullsfirst_op(a: Any) -> Any:
...
else:
nullsfirst_op = nulls_first_op
@@ -2426,7 +2408,8 @@ def nulls_last_op(a: Any) -> Any:
if TYPE_CHECKING:
@_operator_fn
def nullslast_op(a: Any) -> Any: ...
def nullslast_op(a: Any) -> Any:
...
else:
nullslast_op = nulls_last_op
@@ -2518,12 +2501,6 @@ def is_associative(op: OperatorType) -> bool:
return op in _associative
def is_order_by_modifier(op: Optional[OperatorType]) -> bool:
return op in _order_by_modifier
_order_by_modifier = {desc_op, asc_op, nulls_first_op, nulls_last_op}
_natural_self_precedent = _associative.union(
[getitem, json_getitem_op, json_path_getitem_op]
)
@@ -2605,13 +2582,9 @@ _PRECEDENCE: Dict[OperatorType, int] = {
}
def is_precedent(
operator: OperatorType, against: Optional[OperatorType]
) -> bool:
def is_precedent(operator: OperatorType, against: OperatorType) -> bool:
if operator is against and is_natural_self_precedent(operator):
return False
elif against is None:
return True
else:
return bool(
_PRECEDENCE.get(