summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2020-10-30 15:14:18 +0000
committerGerrit Code Review <gerrit@bbpush.zzzcomputing.com>2020-10-30 15:14:18 +0000
commit841eb216644202567ebddfc0badc51a3a35e98c3 (patch)
tree40f930139e5a5fb707c3c3090bd2aabb455dd9cb /lib
parent163a97c6d57db09d6405124dae9b877bc9629721 (diff)
parent9ddbd585a62ff1ad56e9ee6fef5898ced1932a88 (diff)
downloadsqlalchemy-841eb216644202567ebddfc0badc51a3a35e98c3.tar.gz
Merge "Apply underscore naming to several more operators"
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/__init__.py6
-rw-r--r--lib/sqlalchemy/dialects/firebird/base.py4
-rw-r--r--lib/sqlalchemy/dialects/mssql/base.py4
-rw-r--r--lib/sqlalchemy/dialects/mysql/base.py2
-rw-r--r--lib/sqlalchemy/dialects/oracle/base.py2
-rw-r--r--lib/sqlalchemy/dialects/postgresql/base.py6
-rw-r--r--lib/sqlalchemy/dialects/sqlite/base.py2
-rw-r--r--lib/sqlalchemy/engine/reflection.py6
-rw-r--r--lib/sqlalchemy/orm/evaluator.py4
-rw-r--r--lib/sqlalchemy/sql/__init__.py6
-rw-r--r--lib/sqlalchemy/sql/compiler.py32
-rw-r--r--lib/sqlalchemy/sql/default_comparator.py37
-rw-r--r--lib/sqlalchemy/sql/elements.py58
-rw-r--r--lib/sqlalchemy/sql/expression.py14
-rw-r--r--lib/sqlalchemy/sql/operators.py164
-rw-r--r--lib/sqlalchemy/testing/suite/test_select.py4
16 files changed, 226 insertions, 125 deletions
diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py
index d2c99b5b2..1146803f5 100644
--- a/lib/sqlalchemy/__init__.py
+++ b/lib/sqlalchemy/__init__.py
@@ -61,8 +61,10 @@ from .sql import literal_column # noqa
from .sql import modifier # noqa
from .sql import not_ # noqa
from .sql import null # noqa
-from .sql import nullsfirst # noqa
-from .sql import nullslast # noqa
+from .sql import nullsfirst # noqa; deprecated 1.4; see #5435
+from .sql import nullslast # noqa; deprecated 1.4; see #5435
+from .sql import nulls_first # noqa
+from .sql import nulls_last # noqa
from .sql import or_ # noqa
from .sql import outerjoin # noqa
from .sql import outparam # noqa
diff --git a/lib/sqlalchemy/dialects/firebird/base.py b/lib/sqlalchemy/dialects/firebird/base.py
index 680968b9e..8a110fbd3 100644
--- a/lib/sqlalchemy/dialects/firebird/base.py
+++ b/lib/sqlalchemy/dialects/firebird/base.py
@@ -439,7 +439,7 @@ class FBCompiler(sql.compiler.SQLCompiler):
# def visit_contains_op_binary(self, binary, operator, **kw):
# cant use CONTAINING b.c. it's case insensitive.
- # def visit_notcontains_op_binary(self, binary, operator, **kw):
+ # def visit_not_contains_op_binary(self, binary, operator, **kw):
# cant use NOT CONTAINING b.c. it's case insensitive.
def visit_now_func(self, fn, **kw):
@@ -451,7 +451,7 @@ class FBCompiler(sql.compiler.SQLCompiler):
binary.right._compiler_dispatch(self, **kw),
)
- def visit_notstartswith_op_binary(self, binary, operator, **kw):
+ def visit_not_startswith_op_binary(self, binary, operator, **kw):
return "%s NOT STARTING WITH %s" % (
binary.left._compiler_dispatch(self, **kw),
binary.right._compiler_dispatch(self, **kw),
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py
index a224c00bb..bfe7a00ba 100644
--- a/lib/sqlalchemy/dialects/mssql/base.py
+++ b/lib/sqlalchemy/dialects/mssql/base.py
@@ -2077,7 +2077,7 @@ class MSSQLCompiler(compiler.SQLCompiler):
self.process(binary.right),
)
- def visit_isnot_distinct_from_binary(self, binary, operator, **kw):
+ def visit_is_not_distinct_from_binary(self, binary, operator, **kw):
return "EXISTS (SELECT %s INTERSECT SELECT %s)" % (
self.process(binary.left),
self.process(binary.right),
@@ -2165,7 +2165,7 @@ class MSSQLStrictCompiler(MSSQLCompiler):
self.process(binary.right, **kw),
)
- def visit_notin_op_binary(self, binary, operator, **kw):
+ def visit_not_in_op_binary(self, binary, operator, **kw):
kw["literal_execute"] = True
return "%s NOT IN %s" % (
self.process(binary.left, **kw),
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py
index 77f65799c..04175dedf 100644
--- a/lib/sqlalchemy/dialects/mysql/base.py
+++ b/lib/sqlalchemy/dialects/mysql/base.py
@@ -1773,7 +1773,7 @@ class MySQLCompiler(compiler.SQLCompiler):
self.process(binary.right),
)
- def visit_isnot_distinct_from_binary(self, binary, operator, **kw):
+ def visit_is_not_distinct_from_binary(self, binary, operator, **kw):
return "%s <=> %s" % (
self.process(binary.left),
self.process(binary.right),
diff --git a/lib/sqlalchemy/dialects/oracle/base.py b/lib/sqlalchemy/dialects/oracle/base.py
index 1f1f7501b..7bdaafd82 100644
--- a/lib/sqlalchemy/dialects/oracle/base.py
+++ b/lib/sqlalchemy/dialects/oracle/base.py
@@ -1213,7 +1213,7 @@ class OracleCompiler(compiler.SQLCompiler):
self.process(binary.right),
)
- def visit_isnot_distinct_from_binary(self, binary, operator, **kw):
+ def visit_is_not_distinct_from_binary(self, binary, operator, **kw):
return "DECODE(%s, %s, 0, 1) = 0" % (
self.process(binary.left),
self.process(binary.right),
diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py
index ea6921b2d..391361e23 100644
--- a/lib/sqlalchemy/dialects/postgresql/base.py
+++ b/lib/sqlalchemy/dialects/postgresql/base.py
@@ -1865,7 +1865,7 @@ class PGCompiler(compiler.SQLCompiler):
else ""
)
- def visit_notilike_op_binary(self, binary, operator, **kw):
+ def visit_not_ilike_op_binary(self, binary, operator, **kw):
escape = binary.modifiers.get("escape", None)
return "%s NOT ILIKE %s" % (
self.process(binary.left, **kw),
@@ -3850,10 +3850,10 @@ class PGDialect(default.DefaultDialect):
if col_flags & 0x01:
col_sorting += ("desc",)
if not (col_flags & 0x02):
- col_sorting += ("nullslast",)
+ col_sorting += ("nulls_last",)
else:
if col_flags & 0x02:
- col_sorting += ("nullsfirst",)
+ col_sorting += ("nulls_first",)
if col_sorting:
sorting[col_idx] = col_sorting
if sorting:
diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py
index 8a4fbe8e5..5efd0d9c9 100644
--- a/lib/sqlalchemy/dialects/sqlite/base.py
+++ b/lib/sqlalchemy/dialects/sqlite/base.py
@@ -1043,7 +1043,7 @@ class SQLiteCompiler(compiler.SQLCompiler):
self.process(binary.right),
)
- def visit_isnot_distinct_from_binary(self, binary, operator, **kw):
+ def visit_is_not_distinct_from_binary(self, binary, operator, **kw):
return "%s IS %s" % (
self.process(binary.left),
self.process(binary.right),
diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py
index 6af74d052..daebfe263 100644
--- a/lib/sqlalchemy/engine/reflection.py
+++ b/lib/sqlalchemy/engine/reflection.py
@@ -581,7 +581,7 @@ class Inspector(object):
* ``column_sorting`` -
optional dict mapping column names to tuple of sort keywords,
- which may include ``asc``, ``desc``, ``nullsfirst``, ``nullslast``.
+ which may include ``asc``, ``desc``, ``nulls_first``, ``nulls_last``.
.. versionadded:: 1.3.5
@@ -1006,8 +1006,8 @@ class Inspector(object):
_index_sort_exprs = [
("asc", operators.asc_op),
("desc", operators.desc_op),
- ("nullsfirst", operators.nullsfirst_op),
- ("nullslast", operators.nullslast_op),
+ ("nulls_first", operators.nulls_first_op),
+ ("nulls_last", operators.nulls_last_op),
]
def _reflect_indexes(
diff --git a/lib/sqlalchemy/orm/evaluator.py b/lib/sqlalchemy/orm/evaluator.py
index 23c48329d..8763f0a3d 100644
--- a/lib/sqlalchemy/orm/evaluator.py
+++ b/lib/sqlalchemy/orm/evaluator.py
@@ -56,9 +56,9 @@ _notimplemented_ops = set(
getattr(operators, op)
for op in (
"like_op",
- "notlike_op",
+ "not_like_op",
"ilike_op",
- "notilike_op",
+ "not_ilike_op",
"startswith_op",
"between_op",
"endswith_op",
diff --git a/lib/sqlalchemy/sql/__init__.py b/lib/sqlalchemy/sql/__init__.py
index 8f6dc8e72..8cfd20054 100644
--- a/lib/sqlalchemy/sql/__init__.py
+++ b/lib/sqlalchemy/sql/__init__.py
@@ -55,8 +55,10 @@ from .expression import literal_column # noqa
from .expression import modifier # noqa
from .expression import not_ # noqa
from .expression import null # noqa
-from .expression import nullsfirst # noqa
-from .expression import nullslast # noqa
+from .expression import nullsfirst # noqa; deprecated 1.4; see #5435
+from .expression import nullslast # noqa; deprecated 1.4; see #5435
+from .expression import nulls_first # noqa
+from .expression import nulls_last # noqa
from .expression import or_ # noqa
from .expression import outerjoin # noqa
from .expression import outparam # noqa
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 10499975c..23c9d5c0a 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -185,10 +185,10 @@ OPERATORS = {
operators.ge: " >= ",
operators.eq: " = ",
operators.is_distinct_from: " IS DISTINCT FROM ",
- operators.isnot_distinct_from: " IS NOT DISTINCT FROM ",
+ operators.is_not_distinct_from: " IS NOT DISTINCT FROM ",
operators.concat_op: " || ",
operators.match_op: " MATCH ",
- operators.notmatch_op: " NOT MATCH ",
+ operators.not_match_op: " NOT MATCH ",
operators.in_op: " IN ",
operators.not_in_op: " NOT IN ",
operators.comma_op: ", ",
@@ -206,8 +206,8 @@ OPERATORS = {
# modifiers
operators.desc_op: " DESC",
operators.asc_op: " ASC",
- operators.nullsfirst_op: " NULLS FIRST",
- operators.nullslast_op: " NULLS LAST",
+ operators.nulls_first_op: " NULLS FIRST",
+ operators.nulls_last_op: " NULLS LAST",
}
FUNCTIONS = {
@@ -1860,7 +1860,7 @@ class SQLCompiler(Compiled):
"Unary expression has no operator or modifier"
)
- def visit_istrue_unary_operator(self, element, operator, **kw):
+ def visit_is_true_unary_operator(self, element, operator, **kw):
if (
element._is_implicitly_boolean
or self.dialect.supports_native_boolean
@@ -1869,7 +1869,7 @@ class SQLCompiler(Compiled):
else:
return "%s = 1" % self.process(element.element, **kw)
- def visit_isfalse_unary_operator(self, element, operator, **kw):
+ def visit_is_false_unary_operator(self, element, operator, **kw):
if (
element._is_implicitly_boolean
or self.dialect.supports_native_boolean
@@ -1878,7 +1878,7 @@ class SQLCompiler(Compiled):
else:
return "%s = 0" % self.process(element.element, **kw)
- def visit_notmatch_op_binary(self, binary, operator, **kw):
+ def visit_not_match_op_binary(self, binary, operator, **kw):
return "NOT %s" % self.visit_binary(
binary, override_operator=operators.match_op
)
@@ -2083,11 +2083,11 @@ class SQLCompiler(Compiled):
binary.right = percent.__add__(binary.right).__add__(percent)
return self.visit_like_op_binary(binary, operator, **kw)
- def visit_notcontains_op_binary(self, binary, operator, **kw):
+ def visit_not_contains_op_binary(self, binary, operator, **kw):
binary = binary._clone()
percent = self._like_percent_literal
binary.right = percent.__add__(binary.right).__add__(percent)
- return self.visit_notlike_op_binary(binary, operator, **kw)
+ return self.visit_not_like_op_binary(binary, operator, **kw)
def visit_startswith_op_binary(self, binary, operator, **kw):
binary = binary._clone()
@@ -2095,11 +2095,11 @@ class SQLCompiler(Compiled):
binary.right = percent.__radd__(binary.right)
return self.visit_like_op_binary(binary, operator, **kw)
- def visit_notstartswith_op_binary(self, binary, operator, **kw):
+ def visit_not_startswith_op_binary(self, binary, operator, **kw):
binary = binary._clone()
percent = self._like_percent_literal
binary.right = percent.__radd__(binary.right)
- return self.visit_notlike_op_binary(binary, operator, **kw)
+ return self.visit_not_like_op_binary(binary, operator, **kw)
def visit_endswith_op_binary(self, binary, operator, **kw):
binary = binary._clone()
@@ -2107,11 +2107,11 @@ class SQLCompiler(Compiled):
binary.right = percent.__add__(binary.right)
return self.visit_like_op_binary(binary, operator, **kw)
- def visit_notendswith_op_binary(self, binary, operator, **kw):
+ def visit_not_endswith_op_binary(self, binary, operator, **kw):
binary = binary._clone()
percent = self._like_percent_literal
binary.right = percent.__add__(binary.right)
- return self.visit_notlike_op_binary(binary, operator, **kw)
+ return self.visit_not_like_op_binary(binary, operator, **kw)
def visit_like_op_binary(self, binary, operator, **kw):
escape = binary.modifiers.get("escape", None)
@@ -2126,7 +2126,7 @@ class SQLCompiler(Compiled):
else ""
)
- def visit_notlike_op_binary(self, binary, operator, **kw):
+ def visit_not_like_op_binary(self, binary, operator, **kw):
escape = binary.modifiers.get("escape", None)
return "%s NOT LIKE %s" % (
binary.left._compiler_dispatch(self, **kw),
@@ -2148,7 +2148,7 @@ class SQLCompiler(Compiled):
else ""
)
- def visit_notilike_op_binary(self, binary, operator, **kw):
+ def visit_not_ilike_op_binary(self, binary, operator, **kw):
escape = binary.modifiers.get("escape", None)
return "lower(%s) NOT LIKE lower(%s)" % (
binary.left._compiler_dispatch(self, **kw),
@@ -2165,7 +2165,7 @@ class SQLCompiler(Compiled):
binary, " BETWEEN SYMMETRIC " if symmetric else " BETWEEN ", **kw
)
- def visit_notbetween_op_binary(self, binary, operator, **kw):
+ def visit_not_between_op_binary(self, binary, operator, **kw):
symmetric = binary.modifiers.get("symmetric", False)
return self._generate_generic_binary(
binary,
diff --git a/lib/sqlalchemy/sql/default_comparator.py b/lib/sqlalchemy/sql/default_comparator.py
index d5762ff1f..be6d0787b 100644
--- a/lib/sqlalchemy/sql/default_comparator.py
+++ b/lib/sqlalchemy/sql/default_comparator.py
@@ -57,7 +57,10 @@ def _boolean_compare(
negate=negate,
modifiers=kwargs,
)
- elif op in (operators.is_distinct_from, operators.isnot_distinct_from):
+ elif op in (
+ operators.is_distinct_from,
+ operators.is_not_distinct_from,
+ ):
return BinaryExpression(
expr,
coercions.expect(roles.ConstExprRole, obj),
@@ -87,7 +90,7 @@ def _boolean_compare(
else:
raise exc.ArgumentError(
"Only '=', '!=', 'is_()', 'is_not()', "
- "'is_distinct_from()', 'isnot_distinct_from()' "
+ "'is_distinct_from()', 'is_not_distinct_from()' "
"operators can be used with None/True/False"
)
else:
@@ -205,7 +208,7 @@ def _match_impl(expr, op, other, **kw):
operator=operators.match_op,
),
result_type=type_api.MATCHTYPE,
- negate=operators.notmatch_op
+ negate=operators.not_match_op
if op is operators.match_op
else operators.match_op,
**kw
@@ -241,7 +244,7 @@ def _between_impl(expr, op, cleft, cright, **kw):
group_contents=False,
),
op,
- negate=operators.notbetween_op
+ negate=operators.not_between_op
if op is operators.between_op
else operators.between_op,
modifiers=kw,
@@ -315,29 +318,29 @@ operator_lookup = {
"gt": (_boolean_compare, operators.le),
"ge": (_boolean_compare, operators.lt),
"eq": (_boolean_compare, operators.ne),
- "is_distinct_from": (_boolean_compare, operators.isnot_distinct_from),
- "isnot_distinct_from": (_boolean_compare, operators.is_distinct_from),
- "like_op": (_boolean_compare, operators.notlike_op),
- "ilike_op": (_boolean_compare, operators.notilike_op),
- "notlike_op": (_boolean_compare, operators.like_op),
- "notilike_op": (_boolean_compare, operators.ilike_op),
- "contains_op": (_boolean_compare, operators.notcontains_op),
- "startswith_op": (_boolean_compare, operators.notstartswith_op),
- "endswith_op": (_boolean_compare, operators.notendswith_op),
+ "is_distinct_from": (_boolean_compare, operators.is_not_distinct_from),
+ "is_not_distinct_from": (_boolean_compare, operators.is_distinct_from),
+ "like_op": (_boolean_compare, operators.not_like_op),
+ "ilike_op": (_boolean_compare, operators.not_ilike_op),
+ "not_like_op": (_boolean_compare, operators.like_op),
+ "not_ilike_op": (_boolean_compare, operators.ilike_op),
+ "contains_op": (_boolean_compare, operators.not_contains_op),
+ "startswith_op": (_boolean_compare, operators.not_startswith_op),
+ "endswith_op": (_boolean_compare, operators.not_endswith_op),
"desc_op": (_scalar, UnaryExpression._create_desc),
"asc_op": (_scalar, UnaryExpression._create_asc),
- "nullsfirst_op": (_scalar, UnaryExpression._create_nullsfirst),
- "nullslast_op": (_scalar, UnaryExpression._create_nullslast),
+ "nulls_first_op": (_scalar, UnaryExpression._create_nulls_first),
+ "nulls_last_op": (_scalar, UnaryExpression._create_nulls_last),
"in_op": (_in_impl, operators.not_in_op),
"not_in_op": (_in_impl, operators.in_op),
"is_": (_boolean_compare, operators.is_),
"is_not": (_boolean_compare, operators.is_not),
"collate": (_collate_impl,),
"match_op": (_match_impl,),
- "notmatch_op": (_match_impl,),
+ "not_match_op": (_match_impl,),
"distinct_op": (_distinct_impl,),
"between_op": (_between_impl,),
- "notbetween_op": (_between_impl,),
+ "not_between_op": (_between_impl,),
"neg": (_neg_impl,),
"getitem": (_getitem_impl,),
"lshift": (_unsupported_impl,),
diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py
index 00e28ac20..e268abc8a 100644
--- a/lib/sqlalchemy/sql/elements.py
+++ b/lib/sqlalchemy/sql/elements.py
@@ -766,7 +766,7 @@ class ColumnElement(
against in (operators.and_, operators.or_, operators._asbool)
and self.type._type_affinity is type_api.BOOLEANTYPE._type_affinity
):
- return AsBoolean(self, operators.istrue, operators.isfalse)
+ return AsBoolean(self, operators.is_true, operators.is_false)
elif against in (operators.any_op, operators.all_op):
return Grouping(self)
else:
@@ -774,7 +774,7 @@ class ColumnElement(
def _negate(self):
if self.type._type_affinity is type_api.BOOLEANTYPE._type_affinity:
- return AsBoolean(self, operators.isfalse, operators.istrue)
+ return AsBoolean(self, operators.is_false, operators.is_true)
else:
return super(ColumnElement, self)._negate()
@@ -3096,7 +3096,7 @@ class UnaryExpression(ColumnElement):
:class:`.UnaryExpression` is the basis for several unary operators
including those used by :func:`.desc`, :func:`.asc`, :func:`.distinct`,
- :func:`.nullsfirst` and :func:`.nullslast`.
+ :func:`.nulls_first` and :func:`.nulls_last`.
"""
@@ -3126,31 +3126,35 @@ class UnaryExpression(ColumnElement):
self.wraps_column_expression = wraps_column_expression
@classmethod
- def _create_nullsfirst(cls, column):
+ def _create_nulls_first(cls, column):
"""Produce the ``NULLS FIRST`` modifier for an ``ORDER BY`` expression.
- :func:`.nullsfirst` is intended to modify the expression produced
+ :func:`.nulls_first` is intended to modify the expression produced
by :func:`.asc` or :func:`.desc`, and indicates how NULL values
should be handled when they are encountered during ordering::
- from sqlalchemy import desc, nullsfirst
+ from sqlalchemy import desc, nulls_first
stmt = select(users_table).order_by(
- nullsfirst(desc(users_table.c.name)))
+ nulls_first(desc(users_table.c.name)))
The SQL expression from the above would resemble::
SELECT id, name FROM user ORDER BY name DESC NULLS FIRST
- Like :func:`.asc` and :func:`.desc`, :func:`.nullsfirst` is typically
+ Like :func:`.asc` and :func:`.desc`, :func:`.nulls_first` is typically
invoked from the column expression itself using
- :meth:`_expression.ColumnElement.nullsfirst`,
+ :meth:`_expression.ColumnElement.nulls_first`,
rather than as its standalone
function version, as in::
stmt = select(users_table).order_by(
- users_table.c.name.desc().nullsfirst())
+ users_table.c.name.desc().nulls_first())
+
+ .. versionchanged:: 1.4 :func:`.nulls_first` is renamed from
+ :func:`.nullsfirst` in previous releases.
+ The previous name remains available for backwards compatibility.
.. seealso::
@@ -3158,43 +3162,47 @@ class UnaryExpression(ColumnElement):
:func:`.desc`
- :func:`.nullslast`
+ :func:`.nulls_last`
:meth:`_expression.Select.order_by`
"""
return UnaryExpression(
coercions.expect(roles.ByOfRole, column),
- modifier=operators.nullsfirst_op,
+ modifier=operators.nulls_first_op,
wraps_column_expression=False,
)
@classmethod
- def _create_nullslast(cls, column):
+ def _create_nulls_last(cls, column):
"""Produce the ``NULLS LAST`` modifier for an ``ORDER BY`` expression.
- :func:`.nullslast` is intended to modify the expression produced
+ :func:`.nulls_last` is intended to modify the expression produced
by :func:`.asc` or :func:`.desc`, and indicates how NULL values
should be handled when they are encountered during ordering::
- from sqlalchemy import desc, nullslast
+ from sqlalchemy import desc, nulls_last
stmt = select(users_table).order_by(
- nullslast(desc(users_table.c.name)))
+ nulls_last(desc(users_table.c.name)))
The SQL expression from the above would resemble::
SELECT id, name FROM user ORDER BY name DESC NULLS LAST
- Like :func:`.asc` and :func:`.desc`, :func:`.nullslast` is typically
+ Like :func:`.asc` and :func:`.desc`, :func:`.nulls_last` is typically
invoked from the column expression itself using
- :meth:`_expression.ColumnElement.nullslast`,
+ :meth:`_expression.ColumnElement.nulls_last`,
rather than as its standalone
function version, as in::
stmt = select(users_table).order_by(
- users_table.c.name.desc().nullslast())
+ users_table.c.name.desc().nulls_last())
+
+ .. versionchanged:: 1.4 :func:`.nulls_last` is renamed from
+ :func:`.nullslast` in previous releases.
+ The previous name remains available for backwards compatibility.
.. seealso::
@@ -3202,14 +3210,14 @@ class UnaryExpression(ColumnElement):
:func:`.desc`
- :func:`.nullsfirst`
+ :func:`.nulls_first`
:meth:`_expression.Select.order_by`
"""
return UnaryExpression(
coercions.expect(roles.ByOfRole, column),
- modifier=operators.nullslast_op,
+ modifier=operators.nulls_last_op,
wraps_column_expression=False,
)
@@ -3243,9 +3251,9 @@ class UnaryExpression(ColumnElement):
:func:`.asc`
- :func:`.nullsfirst`
+ :func:`.nulls_first`
- :func:`.nullslast`
+ :func:`.nulls_last`
:meth:`_expression.Select.order_by`
@@ -3285,9 +3293,9 @@ class UnaryExpression(ColumnElement):
:func:`.desc`
- :func:`.nullsfirst`
+ :func:`.nulls_first`
- :func:`.nullslast`
+ :func:`.nulls_last`
:meth:`_expression.Select.order_by`
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 31584f072..a3a4ec351 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -67,8 +67,8 @@ __all__ = [
"literal_column",
"not_",
"null",
- "nullsfirst",
- "nullslast",
+ "nulls_first",
+ "nulls_last",
"or_",
"outparam",
"outerjoin",
@@ -220,12 +220,14 @@ union_all = public_factory(
CompoundSelect._create_union_all, ".sql.expression.union_all"
)
exists = public_factory(Exists, ".sql.expression.exists")
-nullsfirst = public_factory(
- UnaryExpression._create_nullsfirst, ".sql.expression.nullsfirst"
+nulls_first = public_factory(
+ UnaryExpression._create_nulls_first, ".sql.expression.nulls_first"
)
-nullslast = public_factory(
- UnaryExpression._create_nullslast, ".sql.expression.nullslast"
+nullsfirst = nulls_first # deprecated 1.4; see #5435
+nulls_last = public_factory(
+ UnaryExpression._create_nulls_last, ".sql.expression.nulls_last"
)
+nullslast = nulls_last # deprecated 1.4; see #5435
asc = public_factory(UnaryExpression._create_asc, ".sql.expression.asc")
desc = public_factory(UnaryExpression._create_desc, ".sql.expression.desc")
distinct = public_factory(
diff --git a/lib/sqlalchemy/sql/operators.py b/lib/sqlalchemy/sql/operators.py
index 5f5052c28..29a2f191e 100644
--- a/lib/sqlalchemy/sql/operators.py
+++ b/lib/sqlalchemy/sql/operators.py
@@ -379,16 +379,23 @@ class ColumnOperators(Operators):
"""
return self.operate(is_distinct_from, other)
- def isnot_distinct_from(self, other):
+ def is_not_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".
+ .. versionchanged:: 1.4 The ``is_not_distinct_from()`` operator is
+ renamed from ``isnot_distinct_from()`` in previous releases.
+ The previous name remains available for backwards compatibility.
+
.. versionadded:: 1.1
"""
- return self.operate(isnot_distinct_from, other)
+ return self.operate(is_not_distinct_from, other)
+
+ # deprecated 1.4; see #5435
+ isnot_distinct_from = is_not_distinct_from
def __gt__(self, other):
"""Implement the ``>`` operator.
@@ -627,12 +634,16 @@ class ColumnOperators(Operators):
# deprecated 1.4; see #5429
notin_ = not_in
- def notlike(self, other, escape=None):
+ def not_like(self, other, escape=None):
"""implement the ``NOT LIKE`` operator.
This is equivalent to using negation with
:meth:`.ColumnOperators.like`, i.e. ``~x.like(y)``.
+ .. versionchanged:: 1.4 The ``not_like()`` operator is renamed from
+ ``notlike()`` in previous releases. The previous name remains
+ available for backwards compatibility.
+
.. seealso::
:meth:`.ColumnOperators.like`
@@ -640,12 +651,19 @@ class ColumnOperators(Operators):
"""
return self.operate(notlike_op, other, escape=escape)
- def notilike(self, other, escape=None):
+ # deprecated 1.4; see #5435
+ notlike = not_like
+
+ def not_ilike(self, other, escape=None):
"""implement the ``NOT ILIKE`` operator.
This is equivalent to using negation with
:meth:`.ColumnOperators.ilike`, i.e. ``~x.ilike(y)``.
+ .. versionchanged:: 1.4 The ``not_ilike()`` operator is renamed from
+ ``notilike()`` in previous releases. The previous name remains
+ available for backwards compatibility.
+
.. seealso::
:meth:`.ColumnOperators.ilike`
@@ -653,6 +671,9 @@ class ColumnOperators(Operators):
"""
return self.operate(notilike_op, other, escape=escape)
+ # deprecated 1.4; see #5435
+ notilike = not_ilike
+
def is_(self, other):
"""Implement the ``IS`` operator.
@@ -678,7 +699,6 @@ class ColumnOperators(Operators):
``isnot()`` in previous releases. The previous name remains
available for backwards compatibility.
-
.. seealso:: :meth:`.ColumnOperators.is_`
"""
@@ -1043,15 +1063,31 @@ class ColumnOperators(Operators):
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 nulls_first(self):
+ """Produce a :func:`_expression.nulls_first` clause against the
+ parent object.
- def nullslast(self):
- """Produce a :func:`_expression.nullslast` clause against the
- parent object."""
- return self.operate(nullslast_op)
+ .. versionchanged:: 1.4 The ``nulls_first()`` operator is
+ renamed from ``nullsfirst()`` in previous releases.
+ The previous name remains available for backwards compatibility.
+ """
+ return self.operate(nulls_first_op)
+
+ # deprecated 1.4; see #5435
+ nullsfirst = nulls_first
+
+ def nulls_last(self):
+ """Produce a :func:`_expression.nulls_last` clause against the
+ parent object.
+
+ .. versionchanged:: 1.4 The ``nulls_last()`` operator is
+ renamed from ``nullslast()`` in previous releases.
+ The previous name remains available for backwards compatibility.
+ """
+ return self.operate(nulls_last_op)
+
+ # deprecated 1.4; see #5429
+ nullslast = nulls_last
def collate(self, collation):
"""Produce a :func:`_expression.collate` clause against
@@ -1260,22 +1296,34 @@ def exists():
raise NotImplementedError()
-def istrue(a):
+def is_true(a):
raise NotImplementedError()
-def isfalse(a):
+# 1.4 deprecated; see #5435
+istrue = is_true
+
+
+def is_false(a):
raise NotImplementedError()
+# 1.4 deprecated; see #5435
+isfalse = is_false
+
+
@comparison_op
def is_distinct_from(a, b):
return a.is_distinct_from(b)
@comparison_op
-def isnot_distinct_from(a, b):
- return a.isnot_distinct_from(b)
+def is_not_distinct_from(a, b):
+ return a.is_not_distinct_from(b)
+
+
+# deprecated 1.4; see #5435
+isnot_distinct_from = is_not_distinct_from
@comparison_op
@@ -1306,18 +1354,26 @@ def like_op(a, b, escape=None):
@comparison_op
-def notlike_op(a, b, escape=None):
+def not_like_op(a, b, escape=None):
return a.notlike(b, escape=escape)
+# 1.4 deprecated; see #5435
+notlike_op = not_like_op
+
+
@comparison_op
def ilike_op(a, b, escape=None):
return a.ilike(b, escape=escape)
@comparison_op
-def notilike_op(a, b, escape=None):
- return a.notilike(b, escape=escape)
+def not_ilike_op(a, b, escape=None):
+ return a.not_ilike(b, escape=escape)
+
+
+# 1.4 deprecated; see #5435
+notilike_op = not_ilike_op
@comparison_op
@@ -1326,8 +1382,12 @@ def between_op(a, b, c, symmetric=False):
@comparison_op
-def notbetween_op(a, b, c, symmetric=False):
- return a.notbetween(b, c, symmetric=symmetric)
+def not_between_op(a, b, c, symmetric=False):
+ return ~a.between(b, c, symmetric=symmetric)
+
+
+# 1.4 deprecated; see #5435
+notbetween_op = not_between_op
@comparison_op
@@ -1382,30 +1442,42 @@ def startswith_op(a, b, escape=None, autoescape=False):
@comparison_op
-def notstartswith_op(a, b, escape=None, autoescape=False):
+def not_startswith_op(a, b, escape=None, autoescape=False):
return ~_escaped_like_impl(a.startswith, b, escape, autoescape)
+# 1.4 deprecated; see #5435
+notstartswith_op = not_startswith_op
+
+
@comparison_op
def endswith_op(a, b, escape=None, autoescape=False):
return _escaped_like_impl(a.endswith, b, escape, autoescape)
@comparison_op
-def notendswith_op(a, b, escape=None, autoescape=False):
+def not_endswith_op(a, b, escape=None, autoescape=False):
return ~_escaped_like_impl(a.endswith, b, escape, autoescape)
+# 1.4 deprecated; see #5435
+notendswith_op = not_endswith_op
+
+
@comparison_op
def contains_op(a, b, escape=None, autoescape=False):
return _escaped_like_impl(a.contains, b, escape, autoescape)
@comparison_op
-def notcontains_op(a, b, escape=None, autoescape=False):
+def not_contains_op(a, b, escape=None, autoescape=False):
return ~_escaped_like_impl(a.contains, b, escape, autoescape)
+# 1.4 deprecated; see #5435
+notcontains_op = not_contains_op
+
+
@comparison_op
def match_op(a, b, **kw):
return a.match(b, **kw)
@@ -1426,8 +1498,12 @@ def regexp_replace_op(a, b, replacement, flags=None):
@comparison_op
-def notmatch_op(a, b, **kw):
- return a.notmatch(b, **kw)
+def not_match_op(a, b, **kw):
+ return ~a.match(b, **kw)
+
+
+# 1.4 deprecated; see #5429
+notmatch_op = not_match_op
def comma_op(a, b):
@@ -1450,12 +1526,20 @@ def asc_op(a):
return a.asc()
-def nullsfirst_op(a):
- return a.nullsfirst()
+def nulls_first_op(a):
+ return a.nulls_first()
+
+
+# 1.4 deprecated; see #5435
+nullsfirst_op = nulls_first_op
+
+
+def nulls_last_op(a):
+ return a.nulls_last()
-def nullslast_op(a):
- return a.nullslast()
+# 1.4 deprecated; see #5435
+nullslast_op = nulls_last_op
def json_getitem_op(a, b):
@@ -1475,7 +1559,7 @@ def is_commutative(op):
def is_ordering_modifier(op):
- return op in (asc_op, desc_op, nullsfirst_op, nullslast_op)
+ return op in (asc_op, desc_op, nulls_first_op, nulls_last_op)
def is_natural_self_precedent(op):
@@ -1486,7 +1570,7 @@ def is_natural_self_precedent(op):
)
-_booleans = (inv, istrue, isfalse, and_, or_)
+_booleans = (inv, is_true, is_false, and_, or_)
def is_boolean(op):
@@ -1543,14 +1627,14 @@ _PRECEDENCE = {
concat_op: 6,
filter_op: 6,
match_op: 5,
- notmatch_op: 5,
+ not_match_op: 5,
regexp_match_op: 5,
not_regexp_match_op: 5,
regexp_replace_op: 5,
ilike_op: 5,
- notilike_op: 5,
+ not_ilike_op: 5,
like_op: 5,
- notlike_op: 5,
+ not_like_op: 5,
in_op: 5,
not_in_op: 5,
is_: 5,
@@ -1558,17 +1642,17 @@ _PRECEDENCE = {
eq: 5,
ne: 5,
is_distinct_from: 5,
- isnot_distinct_from: 5,
+ is_not_distinct_from: 5,
gt: 5,
lt: 5,
ge: 5,
le: 5,
between_op: 5,
- notbetween_op: 5,
+ not_between_op: 5,
distinct_op: 5,
inv: 5,
- istrue: 5,
- isfalse: 5,
+ is_true: 5,
+ is_false: 5,
and_: 3,
or_: 2,
comma_op: -1,
diff --git a/lib/sqlalchemy/testing/suite/test_select.py b/lib/sqlalchemy/testing/suite/test_select.py
index ee9db9111..d15fae3c4 100644
--- a/lib/sqlalchemy/testing/suite/test_select.py
+++ b/lib/sqlalchemy/testing/suite/test_select.py
@@ -1349,7 +1349,7 @@ class IsOrIsNotDistinctFromTest(fixtures.TablesTest):
id_="iaaa",
argnames="col_a_value, col_b_value, expected_row_count_for_is",
)
- def test_is_or_isnot_distinct_from(
+ def test_is_or_is_not_distinct_from(
self, col_a_value, col_b_value, expected_row_count_for_is, connection
):
tbl = self.tables.is_distinct_test
@@ -1371,7 +1371,7 @@ class IsOrIsNotDistinctFromTest(fixtures.TablesTest):
1 if expected_row_count_for_is == 0 else 0
)
result = connection.execute(
- tbl.select(tbl.c.col_a.isnot_distinct_from(tbl.c.col_b))
+ tbl.select(tbl.c.col_a.is_not_distinct_from(tbl.c.col_b))
).fetchall()
eq_(
len(result),